Commit 4be5b73dbc1bf70185918d127ffed957ff1e78ae
Committed by
Gitee
!66 新增支付管理的管理后台:商户信息、应用信息、支付订单、退款订单等功能
Merge pull request !66 from 芋道源码/pay_extension
Showing
160 changed files
with
10734 additions
and
258 deletions
.gitignore
sql/change_db.sql
0 → 100644
| 1 | +ALTER TABLE `ruoyi-vue-pro`.`pay_order_extension` | |
| 2 | +CHANGE COLUMN `channel_notify_data` `channel_notify_data` VARCHAR(2048) CHARACTER SET 'utf8mb4' NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容' ; | |
| 3 | + | |
| 4 | +ALTER TABLE `ruoyi-vue-pro`.`pay_refund` | |
| 5 | +CHANGE COLUMN `req_no` `req_no` VARCHAR(64) NULL COMMENT '退款单请求号' ; | |
| 6 | + | |
| 7 | +ALTER TABLE `ruoyi-vue-pro`.`pay_refund` | |
| 8 | +DROP COLUMN `req_no`; | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; | |
| 9 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 10 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 12 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 15 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 16 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 17 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 18 | +import io.swagger.annotations.Api; | |
| 19 | +import io.swagger.annotations.ApiImplicitParam; | |
| 20 | +import io.swagger.annotations.ApiOperation; | |
| 21 | +import lombok.extern.slf4j.Slf4j; | |
| 22 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 23 | +import org.springframework.validation.annotation.Validated; | |
| 24 | +import org.springframework.web.bind.annotation.*; | |
| 25 | + | |
| 26 | +import javax.annotation.Resource; | |
| 27 | +import javax.servlet.http.HttpServletResponse; | |
| 28 | +import javax.validation.Valid; | |
| 29 | +import java.io.IOException; | |
| 30 | +import java.util.*; | |
| 31 | + | |
| 32 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 33 | +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | |
| 34 | + | |
| 35 | +@Slf4j | |
| 36 | +@Api(tags = "支付应用信息") | |
| 37 | +@RestController | |
| 38 | +@RequestMapping("/pay/app") | |
| 39 | +@Validated | |
| 40 | +public class PayAppController { | |
| 41 | + | |
| 42 | + @Resource | |
| 43 | + private PayAppService appService; | |
| 44 | + @Resource | |
| 45 | + private PayChannelService channelService; | |
| 46 | + @Resource | |
| 47 | + private PayMerchantService merchantService; | |
| 48 | + | |
| 49 | + @PostMapping("/create") | |
| 50 | + @ApiOperation("创建支付应用信息") | |
| 51 | + @PreAuthorize("@ss.hasPermission('pay:app:create')") | |
| 52 | + public CommonResult<Long> createApp(@Valid @RequestBody PayAppCreateReqVO createReqVO) { | |
| 53 | + return success(appService.createApp(createReqVO)); | |
| 54 | + } | |
| 55 | + | |
| 56 | + @PutMapping("/update") | |
| 57 | + @ApiOperation("更新支付应用信息") | |
| 58 | + @PreAuthorize("@ss.hasPermission('pay:app:update')") | |
| 59 | + public CommonResult<Boolean> updateApp(@Valid @RequestBody PayAppUpdateReqVO updateReqVO) { | |
| 60 | + appService.updateApp(updateReqVO); | |
| 61 | + return success(true); | |
| 62 | + } | |
| 63 | + | |
| 64 | + @PutMapping("/update-status") | |
| 65 | + @ApiOperation("更新支付应用状态") | |
| 66 | + @PreAuthorize("@ss.hasPermission('pay:app:update')") | |
| 67 | + public CommonResult<Boolean> updateAppStatus(@Valid @RequestBody PayAppUpdateStatusReqVO updateReqVO) { | |
| 68 | + appService.updateAppStatus(updateReqVO.getId(), updateReqVO.getStatus()); | |
| 69 | + return success(true); | |
| 70 | + } | |
| 71 | + | |
| 72 | + @DeleteMapping("/delete") | |
| 73 | + @ApiOperation("删除支付应用信息") | |
| 74 | + @ApiImplicitParam(name = "id", value = "编号", required = true) | |
| 75 | + @PreAuthorize("@ss.hasPermission('pay:app:delete')") | |
| 76 | + public CommonResult<Boolean> deleteApp(@RequestParam("id") Long id) { | |
| 77 | + appService.deleteApp(id); | |
| 78 | + return success(true); | |
| 79 | + } | |
| 80 | + | |
| 81 | + @GetMapping("/get") | |
| 82 | + @ApiOperation("获得支付应用信息") | |
| 83 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | |
| 84 | + @PreAuthorize("@ss.hasPermission('pay:app:query')") | |
| 85 | + public CommonResult<PayAppRespVO> getApp(@RequestParam("id") Long id) { | |
| 86 | + PayAppDO app = appService.getApp(id); | |
| 87 | + return success(PayAppConvert.INSTANCE.convert(app)); | |
| 88 | + } | |
| 89 | + | |
| 90 | + @GetMapping("/list") | |
| 91 | + @ApiOperation("获得支付应用信息列表") | |
| 92 | + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) | |
| 93 | + @PreAuthorize("@ss.hasPermission('pay:app:query')") | |
| 94 | + public CommonResult<List<PayAppRespVO>> getAppList(@RequestParam("ids") Collection<Long> ids) { | |
| 95 | + List<PayAppDO> list = appService.getAppList(ids); | |
| 96 | + return success(PayAppConvert.INSTANCE.convertList(list)); | |
| 97 | + } | |
| 98 | + | |
| 99 | + @GetMapping("/page") | |
| 100 | + @ApiOperation("获得支付应用信息分页") | |
| 101 | + @PreAuthorize("@ss.hasPermission('pay:app:query')") | |
| 102 | + public CommonResult<PageResult<PayAppPageItemRespVO>> getAppPage(@Valid PayAppPageReqVO pageVO) { | |
| 103 | + // 得到应用分页列表 | |
| 104 | + PageResult<PayAppDO> pageResult = appService.getAppPage(pageVO); | |
| 105 | + if (CollUtil.isEmpty(pageResult.getList())) { | |
| 106 | + return success(new PageResult<>(pageResult.getTotal())); | |
| 107 | + } | |
| 108 | + | |
| 109 | + // 得到所有的应用编号,查出所有的通道 | |
| 110 | + Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId); | |
| 111 | + List<PayChannelDO> channels = channelService.getChannelListByAppIds(payAppIds); | |
| 112 | + // TODO @aquan:可以基于 appId 简历一个 multiMap。这样下面,直接 get 到之后,CollUtil buildSet 即可 | |
| 113 | + Iterator<PayChannelDO> iterator = channels.iterator(); | |
| 114 | + | |
| 115 | + // 得到所有的商户信息 | |
| 116 | + Collection<Long> merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId); | |
| 117 | + Map<Long, PayMerchantDO> deptMap = merchantService.getMerchantMap(merchantIds); | |
| 118 | + | |
| 119 | + // 利用反射将通道数据复制到返回的数据结构中去 | |
| 120 | + List<PayAppPageItemRespVO> appList = new ArrayList<>(pageResult.getList().size()); | |
| 121 | + pageResult.getList().forEach(app -> { | |
| 122 | + // 写入应用信息的数据 | |
| 123 | + PayAppPageItemRespVO respVO = PayAppConvert.INSTANCE.pageConvert(app); | |
| 124 | + // 写入商户的数据 | |
| 125 | + respVO.setPayMerchant(PayAppConvert.INSTANCE.convert(deptMap.get(app.getMerchantId()))); | |
| 126 | + // 写入支付渠道信息的数据 | |
| 127 | + Set<String> channelCodes = new HashSet<>(PayChannelEnum.values().length); | |
| 128 | + while (iterator.hasNext()) { | |
| 129 | + PayChannelDO channelDO = iterator.next(); | |
| 130 | + if (channelDO.getAppId().equals(app.getId())) { | |
| 131 | + channelCodes.add(channelDO.getCode()); | |
| 132 | + iterator.remove(); | |
| 133 | + } | |
| 134 | + } | |
| 135 | + respVO.setChannelCodes(channelCodes); | |
| 136 | + appList.add(respVO); | |
| 137 | + }); | |
| 138 | + | |
| 139 | + return success(new PageResult<>(appList, pageResult.getTotal())); | |
| 140 | + } | |
| 141 | + | |
| 142 | + @GetMapping("/export-excel") | |
| 143 | + @ApiOperation("导出支付应用信息 Excel") | |
| 144 | + @PreAuthorize("@ss.hasPermission('pay:app:export')") | |
| 145 | + @OperateLog(type = EXPORT) | |
| 146 | + public void exportAppExcel(@Valid PayAppExportReqVO exportReqVO, | |
| 147 | + HttpServletResponse response) throws IOException { | |
| 148 | + List<PayAppDO> list = appService.getAppList(exportReqVO); | |
| 149 | + // 导出 Excel | |
| 150 | + List<PayAppExcelVO> datas = PayAppConvert.INSTANCE.convertList02(list); | |
| 151 | + ExcelUtils.write(response, "支付应用信息.xls", "数据", PayAppExcelVO.class, datas); | |
| 152 | + } | |
| 153 | + | |
| 154 | + @GetMapping("/list-merchant-id") | |
| 155 | + @ApiOperation("根据商户 ID 查询支付应用信息") | |
| 156 | + @ApiImplicitParam(name = "merchantId", value = "商户ID", required = true, example = "1", dataTypeClass = Long.class) | |
| 157 | + @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | |
| 158 | + public CommonResult<List<PayAppRespVO>> getMerchantListByName(@RequestParam String merchantId) { | |
| 159 | + List<PayAppDO> appListDO = appService.getListByMerchantId(merchantId); | |
| 160 | + return success(PayAppConvert.INSTANCE.convertList(appListDO)); | |
| 161 | + } | |
| 162 | + | |
| 163 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import io.swagger.annotations.*; | |
| 5 | +import javax.validation.constraints.*; | |
| 6 | + | |
| 7 | +/** | |
| 8 | +* 支付应用信息 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 9 | +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 10 | +*/ | |
| 11 | +@Data | |
| 12 | +public class PayAppBaseVO { | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "应用名", required = true) | |
| 15 | + @NotNull(message = "应用名不能为空") | |
| 16 | + private String name; | |
| 17 | + | |
| 18 | + @ApiModelProperty(value = "开启状态", required = true) | |
| 19 | + @NotNull(message = "开启状态不能为空") | |
| 20 | + private Integer status; | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "备注") | |
| 23 | + private String remark; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "支付结果的回调地址", required = true) | |
| 26 | + @NotNull(message = "支付结果的回调地址不能为空") | |
| 27 | + private String payNotifyUrl; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "退款结果的回调地址", required = true) | |
| 30 | + @NotNull(message = "退款结果的回调地址不能为空") | |
| 31 | + private String refundNotifyUrl; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 34 | + @NotNull(message = "商户编号不能为空") | |
| 35 | + private Long merchantId; | |
| 36 | + | |
| 37 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import javax.validation.constraints.*; | |
| 7 | + | |
| 8 | +@ApiModel("支付应用信息创建 Request VO") | |
| 9 | +@Data | |
| 10 | +@EqualsAndHashCode(callSuper = true) | |
| 11 | +@ToString(callSuper = true) | |
| 12 | +public class PayAppCreateReqVO extends PayAppBaseVO { | |
| 13 | + | |
| 14 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | + | |
| 7 | +import com.alibaba.excel.annotation.ExcelProperty; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 支付应用信息 Excel VO | |
| 11 | + * | |
| 12 | + * @author 芋艿 | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +public class PayAppExcelVO { | |
| 16 | + | |
| 17 | + @ExcelProperty("应用编号") | |
| 18 | + private Long id; | |
| 19 | + | |
| 20 | + @ExcelProperty("应用名") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ExcelProperty("开启状态") | |
| 24 | + private Integer status; | |
| 25 | + | |
| 26 | + @ExcelProperty("备注") | |
| 27 | + private String remark; | |
| 28 | + | |
| 29 | + @ExcelProperty("支付结果的回调地址") | |
| 30 | + private String payNotifyUrl; | |
| 31 | + | |
| 32 | + @ExcelProperty("退款结果的回调地址") | |
| 33 | + private String refundNotifyUrl; | |
| 34 | + | |
| 35 | + @ExcelProperty("商户编号") | |
| 36 | + private Long merchantId; | |
| 37 | + | |
| 38 | + @ExcelProperty("创建时间") | |
| 39 | + private Date createTime; | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | + | |
| 11 | +@ApiModel(value = "支付应用信息 Excel 导出 Request VO", description = "参数和 PayAppPageReqVO 是一致的") | |
| 12 | +@Data | |
| 13 | +public class PayAppExportReqVO { | |
| 14 | + | |
| 15 | + @ApiModelProperty(value = "应用名") | |
| 16 | + private String name; | |
| 17 | + | |
| 18 | + @ApiModelProperty(value = "开启状态") | |
| 19 | + private Integer status; | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "备注") | |
| 22 | + private String remark; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "支付结果的回调地址") | |
| 25 | + private String payNotifyUrl; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "退款结果的回调地址") | |
| 28 | + private String refundNotifyUrl; | |
| 29 | + | |
| 30 | + @ApiModelProperty(value = "商户名称") | |
| 31 | + private String merchantName; | |
| 32 | + | |
| 33 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 34 | + @ApiModelProperty(value = "开始创建时间") | |
| 35 | + private Date beginCreateTime; | |
| 36 | + | |
| 37 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 38 | + @ApiModelProperty(value = "结束创建时间") | |
| 39 | + private Date endCreateTime; | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | +import java.util.Set; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 支付应用信息分页查询 Response VO | |
| 14 | + * | |
| 15 | + * @author aquan | |
| 16 | + */ | |
| 17 | +@ApiModel(value = "支付应用信息分页查询 Response VO", description = "相比于支付信息,还会多出应用渠道的开关信息") | |
| 18 | +@Data | |
| 19 | +@EqualsAndHashCode(callSuper = true) | |
| 20 | +@ToString(callSuper = true) | |
| 21 | +public class PayAppPageItemRespVO extends PayAppBaseVO { | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "应用编号", required = true) | |
| 24 | + private Long id; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 27 | + private Date createTime; | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 所属商户 | |
| 31 | + */ | |
| 32 | + private PayMerchant payMerchant; | |
| 33 | + | |
| 34 | + @ApiModel("商户") | |
| 35 | + @Data | |
| 36 | + public static class PayMerchant { | |
| 37 | + | |
| 38 | + @ApiModelProperty(value = "商户编号", required = true, example = "1") | |
| 39 | + private Long id; | |
| 40 | + | |
| 41 | + @ApiModelProperty(value = "商户名称", required = true, example = "研发部") | |
| 42 | + private String name; | |
| 43 | + | |
| 44 | + } | |
| 45 | + | |
| 46 | + @ApiModelProperty(value = "渠道编码集合", required = true, example = "alipay_pc,alipay_wap...") | |
| 47 | + private Set<String> channelCodes; | |
| 48 | + | |
| 49 | + | |
| 50 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | + | |
| 11 | +@ApiModel("支付应用信息分页 Request VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class PayAppPageReqVO extends PageParam { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "应用名") | |
| 18 | + private String name; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "开启状态") | |
| 21 | + private Integer status; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "备注") | |
| 24 | + private String remark; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "支付结果的回调地址") | |
| 27 | + private String payNotifyUrl; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "退款结果的回调地址") | |
| 30 | + private String refundNotifyUrl; | |
| 31 | + | |
| 32 | + @ApiModelProperty(value = "商户名称") | |
| 33 | + private String merchantName; | |
| 34 | + | |
| 35 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 36 | + @ApiModelProperty(value = "开始创建时间") | |
| 37 | + private Date beginCreateTime; | |
| 38 | + | |
| 39 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 40 | + @ApiModelProperty(value = "结束创建时间") | |
| 41 | + private Date endCreateTime; | |
| 42 | + | |
| 43 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | + | |
| 7 | +@ApiModel("支付应用信息 Response VO") | |
| 8 | +@Data | |
| 9 | +@EqualsAndHashCode(callSuper = true) | |
| 10 | +@ToString(callSuper = true) | |
| 11 | +public class PayAppRespVO extends PayAppBaseVO { | |
| 12 | + | |
| 13 | + @ApiModelProperty(value = "应用编号", required = true) | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 17 | + private Date createTime; | |
| 18 | + | |
| 19 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import javax.validation.constraints.*; | |
| 7 | + | |
| 8 | +@ApiModel("支付应用信息更新 Request VO") | |
| 9 | +@Data | |
| 10 | +@EqualsAndHashCode(callSuper = true) | |
| 11 | +@ToString(callSuper = true) | |
| 12 | +public class PayAppUpdateReqVO extends PayAppBaseVO { | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "应用编号", required = true) | |
| 15 | + @NotNull(message = "应用编号不能为空") | |
| 16 | + private Long id; | |
| 17 | + | |
| 18 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import javax.validation.constraints.NotNull; | |
| 8 | + | |
| 9 | +@ApiModel("应用更新状态 Request VO") | |
| 10 | +@Data | |
| 11 | +public class PayAppUpdateStatusReqVO { | |
| 12 | + | |
| 13 | + @ApiModelProperty(value = "商户编号", required = true, example = "1024") | |
| 14 | + @NotNull(message = "商户编号不能为空") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") | |
| 18 | + @NotNull(message = "状态不能为空") | |
| 19 | + private Integer status; | |
| 20 | + | |
| 21 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; | |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 10 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 11 | +import io.swagger.annotations.Api; | |
| 12 | +import io.swagger.annotations.ApiImplicitParam; | |
| 13 | +import io.swagger.annotations.ApiImplicitParams; | |
| 14 | +import io.swagger.annotations.ApiOperation; | |
| 15 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 16 | +import org.springframework.validation.annotation.Validated; | |
| 17 | +import org.springframework.web.bind.annotation.*; | |
| 18 | + | |
| 19 | +import javax.annotation.Resource; | |
| 20 | +import javax.servlet.http.HttpServletResponse; | |
| 21 | +import javax.validation.Valid; | |
| 22 | +import java.io.IOException; | |
| 23 | +import java.util.Collection; | |
| 24 | +import java.util.List; | |
| 25 | + | |
| 26 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 27 | +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * 支付渠道 controller 组件 | |
| 31 | + * @author aquan | |
| 32 | + */ | |
| 33 | +@Api(tags = "支付渠道") | |
| 34 | +@RestController | |
| 35 | +@RequestMapping("/pay/channel") | |
| 36 | +@Validated | |
| 37 | +public class PayChannelController { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private PayChannelService channelService; | |
| 41 | + | |
| 42 | + | |
| 43 | + @PostMapping("/create") | |
| 44 | + @ApiOperation("创建支付渠道 ") | |
| 45 | + @PreAuthorize("@ss.hasPermission('pay:channel:create')") | |
| 46 | + public CommonResult<Long> createChannel(@Valid @RequestBody PayChannelCreateReqVO createReqVO) { | |
| 47 | + return success(channelService.createChannel(createReqVO)); | |
| 48 | + } | |
| 49 | + | |
| 50 | + @PutMapping("/update") | |
| 51 | + @ApiOperation("更新支付渠道 ") | |
| 52 | + @PreAuthorize("@ss.hasPermission('pay:channel:update')") | |
| 53 | + public CommonResult<Boolean> updateChannel(@Valid @RequestBody PayChannelUpdateReqVO updateReqVO) { | |
| 54 | + channelService.updateChannel(updateReqVO); | |
| 55 | + return success(true); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @DeleteMapping("/delete") | |
| 59 | + @ApiOperation("删除支付渠道 ") | |
| 60 | + @ApiImplicitParam(name = "id", value = "编号", required = true) | |
| 61 | + @PreAuthorize("@ss.hasPermission('pay:channel:delete')") | |
| 62 | + public CommonResult<Boolean> deleteChannel(@RequestParam("id") Long id) { | |
| 63 | + channelService.deleteChannel(id); | |
| 64 | + return success(true); | |
| 65 | + } | |
| 66 | + | |
| 67 | + @GetMapping("/get") | |
| 68 | + @ApiOperation("获得支付渠道 ") | |
| 69 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | |
| 70 | + @PreAuthorize("@ss.hasPermission('pay:channel:query')") | |
| 71 | + public CommonResult<PayChannelRespVO> getChannel(@RequestParam("id") Long id) { | |
| 72 | + PayChannelDO channel = channelService.getChannel(id); | |
| 73 | + return success(PayChannelConvert.INSTANCE.convert(channel)); | |
| 74 | + } | |
| 75 | + | |
| 76 | + @GetMapping("/list") | |
| 77 | + @ApiOperation("获得支付渠道列表") | |
| 78 | + @ApiImplicitParam(name = "ids", value = "编号列表", | |
| 79 | + required = true, example = "1024,2048", dataTypeClass = List.class) | |
| 80 | + @PreAuthorize("@ss.hasPermission('pay:channel:query')") | |
| 81 | + public CommonResult<List<PayChannelRespVO>> getChannelList(@RequestParam("ids") Collection<Long> ids) { | |
| 82 | + List<PayChannelDO> list = channelService.getChannelList(ids); | |
| 83 | + return success(PayChannelConvert.INSTANCE.convertList(list)); | |
| 84 | + } | |
| 85 | + | |
| 86 | + @GetMapping("/page") | |
| 87 | + @ApiOperation("获得支付渠道分页") | |
| 88 | + @PreAuthorize("@ss.hasPermission('pay:channel:query')") | |
| 89 | + public CommonResult<PageResult<PayChannelRespVO>> getChannelPage(@Valid PayChannelPageReqVO pageVO) { | |
| 90 | + PageResult<PayChannelDO> pageResult = channelService.getChannelPage(pageVO); | |
| 91 | + return success(PayChannelConvert.INSTANCE.convertPage(pageResult)); | |
| 92 | + } | |
| 93 | + | |
| 94 | + @GetMapping("/export-excel") | |
| 95 | + @ApiOperation("导出支付渠道Excel") | |
| 96 | + @PreAuthorize("@ss.hasPermission('pay:channel:export')") | |
| 97 | + @OperateLog(type = EXPORT) | |
| 98 | + public void exportChannelExcel(@Valid PayChannelExportReqVO exportReqVO, | |
| 99 | + HttpServletResponse response) throws IOException { | |
| 100 | + List<PayChannelDO> list = channelService.getChannelList(exportReqVO); | |
| 101 | + // 导出 Excel | |
| 102 | + List<PayChannelExcelVO> datas = PayChannelConvert.INSTANCE.convertList02(list); | |
| 103 | + ExcelUtils.write(response, "支付渠道.xls", "数据", PayChannelExcelVO.class, datas); | |
| 104 | + } | |
| 105 | + | |
| 106 | + @GetMapping("/get-channel") | |
| 107 | + @ApiOperation("根据条件查询微信支付渠道") | |
| 108 | + @ApiImplicitParams({ | |
| 109 | + @ApiImplicitParam(name = "merchantId", value = "商户编号", | |
| 110 | + required = true, example = "1", dataTypeClass = Long.class), | |
| 111 | + @ApiImplicitParam(name = "appId", value = "应用编号", | |
| 112 | + required = true, example = "1", dataTypeClass = Long.class), | |
| 113 | + @ApiImplicitParam(name = "code", value = "支付渠道编码", | |
| 114 | + required = true, example = "wx_pub", dataTypeClass = String.class) | |
| 115 | + }) | |
| 116 | + @PreAuthorize("@ss.hasPermission('pay:channel:query')") | |
| 117 | + public CommonResult<PayChannelRespVO> getChannel( | |
| 118 | + @RequestParam Long merchantId, @RequestParam Long appId, @RequestParam String code) { | |
| 119 | + | |
| 120 | + // 獲取渠道 | |
| 121 | + PayChannelDO channel = channelService.getChannelByConditions(merchantId, appId, code); | |
| 122 | + if (channel == null) { | |
| 123 | + return success(new PayChannelRespVO()); | |
| 124 | + } | |
| 125 | + // 拼凑数据 | |
| 126 | + PayChannelRespVO respVo = PayChannelConvert.INSTANCE.convert(channel); | |
| 127 | + return success(respVo); | |
| 128 | + } | |
| 129 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import javax.validation.constraints.*; | |
| 7 | + | |
| 8 | +/** | |
| 9 | +* 支付渠道 | |
| 10 | + Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 11 | +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 12 | +*/ | |
| 13 | +@Data | |
| 14 | +public class PayChannelBaseVO { | |
| 15 | + | |
| 16 | + @ApiModelProperty(value = "渠道编码", required = true) | |
| 17 | + @NotNull(message = "渠道编码不能为空") | |
| 18 | + private String code; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "开启状态", required = true) | |
| 21 | + @NotNull(message = "开启状态不能为空") | |
| 22 | + private Integer status; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "备注") | |
| 25 | + private String remark; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "渠道费率,单位:百分比", required = true) | |
| 28 | + @NotNull(message = "渠道费率,单位:百分比不能为空") | |
| 29 | + private Double feeRate; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 32 | + @NotNull(message = "商户编号不能为空") | |
| 33 | + private Long merchantId; | |
| 34 | + | |
| 35 | + @ApiModelProperty(value = "应用编号", required = true) | |
| 36 | + @NotNull(message = "应用编号不能为空") | |
| 37 | + private Long appId; | |
| 38 | + | |
| 39 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import javax.validation.constraints.NotBlank; | |
| 10 | + | |
| 11 | +@ApiModel("支付渠道 创建 Request VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class PayChannelCreateReqVO extends PayChannelBaseVO { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "通道配置的 json 字符串") | |
| 18 | + @NotBlank(message = "通道配置不能为空") | |
| 19 | + private String config; | |
| 20 | + | |
| 21 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | + | |
| 7 | +import com.alibaba.excel.annotation.ExcelProperty; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 支付渠道 | |
| 11 | + Excel VO | |
| 12 | + * | |
| 13 | + * @author 芋艿 | |
| 14 | + */ | |
| 15 | +@Data | |
| 16 | +public class PayChannelExcelVO { | |
| 17 | + | |
| 18 | + @ExcelProperty("商户编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @ExcelProperty("渠道编码") | |
| 22 | + private String code; | |
| 23 | + | |
| 24 | + @ExcelProperty("开启状态") | |
| 25 | + private Integer status; | |
| 26 | + | |
| 27 | + @ExcelProperty("备注") | |
| 28 | + private String remark; | |
| 29 | + | |
| 30 | + @ExcelProperty("渠道费率,单位:百分比") | |
| 31 | + private Double feeRate; | |
| 32 | + | |
| 33 | + @ExcelProperty("商户编号") | |
| 34 | + private Long merchantId; | |
| 35 | + | |
| 36 | + @ExcelProperty("应用编号") | |
| 37 | + private Long appId; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * todo @芋艿 mapStruct 存在转换问题 | |
| 41 | + * java: Can't map property "PayClientConfig payChannelDO.config" to "String payChannelExcelVO.config". | |
| 42 | + * Consider to declare/implement a mapping method: "String map(PayClientConfig value)". | |
| 43 | + */ | |
| 44 | + /// @ExcelProperty("支付渠道配置") | |
| 45 | + /// private String config; | |
| 46 | + | |
| 47 | + @ExcelProperty("创建时间") | |
| 48 | + private Date createTime; | |
| 49 | + | |
| 50 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | + | |
| 11 | +@ApiModel(value = "支付渠道 Excel 导出 Request VO", description = "参数和 PayChannelPageReqVO 是一致的") | |
| 12 | +@Data | |
| 13 | +public class PayChannelExportReqVO { | |
| 14 | + | |
| 15 | + @ApiModelProperty(value = "渠道编码") | |
| 16 | + private String code; | |
| 17 | + | |
| 18 | + @ApiModelProperty(value = "开启状态") | |
| 19 | + private Integer status; | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "备注") | |
| 22 | + private String remark; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "渠道费率,单位:百分比") | |
| 25 | + private Double feeRate; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "商户编号") | |
| 28 | + private Long merchantId; | |
| 29 | + | |
| 30 | + @ApiModelProperty(value = "应用编号") | |
| 31 | + private Long appId; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "支付渠道配置") | |
| 34 | + private String config; | |
| 35 | + | |
| 36 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 37 | + @ApiModelProperty(value = "开始创建时间") | |
| 38 | + private Date beginCreateTime; | |
| 39 | + | |
| 40 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 41 | + @ApiModelProperty(value = "结束创建时间") | |
| 42 | + private Date endCreateTime; | |
| 43 | + | |
| 44 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | + | |
| 11 | +@ApiModel("支付渠道 分页 Request VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class PayChannelPageReqVO extends PageParam { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "渠道编码") | |
| 18 | + private String code; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "开启状态") | |
| 21 | + private Integer status; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "备注") | |
| 24 | + private String remark; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "渠道费率,单位:百分比") | |
| 27 | + private Double feeRate; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "商户编号") | |
| 30 | + private Long merchantId; | |
| 31 | + | |
| 32 | + @ApiModelProperty(value = "应用编号") | |
| 33 | + private Long appId; | |
| 34 | + | |
| 35 | + @ApiModelProperty(value = "支付渠道配置") | |
| 36 | + private String config; | |
| 37 | + | |
| 38 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 39 | + @ApiModelProperty(value = "开始创建时间") | |
| 40 | + private Date beginCreateTime; | |
| 41 | + | |
| 42 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 43 | + @ApiModelProperty(value = "结束创建时间") | |
| 44 | + private Date endCreateTime; | |
| 45 | + | |
| 46 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | + | |
| 7 | +@ApiModel("支付渠道 Response VO") | |
| 8 | +@Data | |
| 9 | +@EqualsAndHashCode(callSuper = true) | |
| 10 | +@ToString(callSuper = true) | |
| 11 | +public class PayChannelRespVO extends PayChannelBaseVO { | |
| 12 | + | |
| 13 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 17 | + private Date createTime; | |
| 18 | + | |
| 19 | + @ApiModelProperty(value = "配置", required = true) | |
| 20 | + private String config; | |
| 21 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import javax.validation.constraints.*; | |
| 7 | + | |
| 8 | +@ApiModel("支付渠道 更新 Request VO") | |
| 9 | +@Data | |
| 10 | +@EqualsAndHashCode(callSuper = true) | |
| 11 | +@ToString(callSuper = true) | |
| 12 | +public class PayChannelUpdateReqVO extends PayChannelBaseVO { | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 15 | + @NotNull(message = "商户编号不能为空") | |
| 16 | + private Long id; | |
| 17 | + | |
| 18 | + @ApiModelProperty(value = "通道配置的json字符串") | |
| 19 | + @NotBlank(message = "通道配置不能为空") | |
| 20 | + private String config; | |
| 21 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; | |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 10 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 11 | +import io.swagger.annotations.Api; | |
| 12 | +import io.swagger.annotations.ApiImplicitParam; | |
| 13 | +import io.swagger.annotations.ApiOperation; | |
| 14 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 15 | +import org.springframework.validation.annotation.Validated; | |
| 16 | +import org.springframework.web.bind.annotation.*; | |
| 17 | + | |
| 18 | +import javax.annotation.Resource; | |
| 19 | +import javax.servlet.http.HttpServletResponse; | |
| 20 | +import javax.validation.Valid; | |
| 21 | +import java.io.IOException; | |
| 22 | +import java.util.Collection; | |
| 23 | +import java.util.List; | |
| 24 | + | |
| 25 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 26 | +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | |
| 27 | + | |
| 28 | +@Api(tags = "支付商户信息") | |
| 29 | +@RestController | |
| 30 | +@RequestMapping("/pay/merchant") | |
| 31 | +@Validated | |
| 32 | +public class PayMerchantController { | |
| 33 | + | |
| 34 | + @Resource | |
| 35 | + private PayMerchantService merchantService; | |
| 36 | + | |
| 37 | + @PostMapping("/create") | |
| 38 | + @ApiOperation("创建支付商户信息") | |
| 39 | + @PreAuthorize("@ss.hasPermission('pay:merchant:create')") | |
| 40 | + public CommonResult<Long> createMerchant(@Valid @RequestBody PayMerchantCreateReqVO createReqVO) { | |
| 41 | + return success(merchantService.createMerchant(createReqVO)); | |
| 42 | + } | |
| 43 | + | |
| 44 | + @PutMapping("/update") | |
| 45 | + @ApiOperation("更新支付商户信息") | |
| 46 | + @PreAuthorize("@ss.hasPermission('pay:merchant:update')") | |
| 47 | + public CommonResult<Boolean> updateMerchant(@Valid @RequestBody PayMerchantUpdateReqVO updateReqVO) { | |
| 48 | + merchantService.updateMerchant(updateReqVO); | |
| 49 | + return success(true); | |
| 50 | + } | |
| 51 | + | |
| 52 | + @PutMapping("/update-status") | |
| 53 | + @ApiOperation("修改支付商户状态") | |
| 54 | + @PreAuthorize("@ss.hasPermission('pay:merchant:update')") | |
| 55 | + public CommonResult<Boolean> updateMerchantStatus(@Valid @RequestBody PayMerchantUpdateStatusReqVO reqVO) { | |
| 56 | + merchantService.updateMerchantStatus(reqVO.getId(), reqVO.getStatus()); | |
| 57 | + return success(true); | |
| 58 | + } | |
| 59 | + | |
| 60 | + @DeleteMapping("/delete") | |
| 61 | + @ApiOperation("删除支付商户信息") | |
| 62 | + @ApiImplicitParam(name = "id", value = "编号", required = true) | |
| 63 | + @PreAuthorize("@ss.hasPermission('pay:merchant:delete')") | |
| 64 | + public CommonResult<Boolean> deleteMerchant(@RequestParam("id") Long id) { | |
| 65 | + merchantService.deleteMerchant(id); | |
| 66 | + return success(true); | |
| 67 | + } | |
| 68 | + | |
| 69 | + @GetMapping("/get") | |
| 70 | + @ApiOperation("获得支付商户信息") | |
| 71 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | |
| 72 | + @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | |
| 73 | + public CommonResult<PayMerchantRespVO> getMerchant(@RequestParam("id") Long id) { | |
| 74 | + PayMerchantDO merchant = merchantService.getMerchant(id); | |
| 75 | + return success(PayMerchantConvert.INSTANCE.convert(merchant)); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @GetMapping("/list-by-name") | |
| 79 | + @ApiOperation("根据商户名称获得支付商户信息列表") | |
| 80 | + @ApiImplicitParam(name = "name", value = "商户名称", example = "芋道", dataTypeClass = Long.class) | |
| 81 | + @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | |
| 82 | + public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam(required = false) String name) { | |
| 83 | + List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByName(name); | |
| 84 | + return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO)); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @GetMapping("/list") | |
| 88 | + @ApiOperation("获得支付商户信息列表") | |
| 89 | + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) | |
| 90 | + @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | |
| 91 | + public CommonResult<List<PayMerchantRespVO>> getMerchantList(@RequestParam("ids") Collection<Long> ids) { | |
| 92 | + List<PayMerchantDO> list = merchantService.getMerchantList(ids); | |
| 93 | + return success(PayMerchantConvert.INSTANCE.convertList(list)); | |
| 94 | + } | |
| 95 | + | |
| 96 | + @GetMapping("/page") | |
| 97 | + @ApiOperation("获得支付商户信息分页") | |
| 98 | + @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | |
| 99 | + public CommonResult<PageResult<PayMerchantRespVO>> getMerchantPage(@Valid PayMerchantPageReqVO pageVO) { | |
| 100 | + PageResult<PayMerchantDO> pageResult = merchantService.getMerchantPage(pageVO); | |
| 101 | + return success(PayMerchantConvert.INSTANCE.convertPage(pageResult)); | |
| 102 | + } | |
| 103 | + | |
| 104 | + @GetMapping("/export-excel") | |
| 105 | + @ApiOperation("导出支付商户信息 Excel") | |
| 106 | + @PreAuthorize("@ss.hasPermission('pay:merchant:export')") | |
| 107 | + @OperateLog(type = EXPORT) | |
| 108 | + public void exportMerchantExcel(@Valid PayMerchantExportReqVO exportReqVO, | |
| 109 | + HttpServletResponse response) throws IOException { | |
| 110 | + List<PayMerchantDO> list = merchantService.getMerchantList(exportReqVO); | |
| 111 | + // 导出 Excel | |
| 112 | + List<PayMerchantExcelVO> datas = PayMerchantConvert.INSTANCE.convertList02(list); | |
| 113 | + ExcelUtils.write(response, "支付商户信息.xls", "数据", PayMerchantExcelVO.class, datas); | |
| 114 | + } | |
| 115 | + | |
| 116 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModelProperty; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import javax.validation.constraints.NotNull; | |
| 7 | + | |
| 8 | +/** | |
| 9 | +* 支付商户信息 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 10 | +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 11 | +*/ | |
| 12 | +@Data | |
| 13 | +public class PayMerchantBaseVO { | |
| 14 | + | |
| 15 | + @ApiModelProperty(value = "商户全称", required = true) | |
| 16 | + @NotNull(message = "商户全称不能为空") | |
| 17 | + private String name; | |
| 18 | + | |
| 19 | + @ApiModelProperty(value = "商户简称", required = true) | |
| 20 | + @NotNull(message = "商户简称不能为空") | |
| 21 | + private String shortName; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "开启状态", required = true) | |
| 24 | + @NotNull(message = "开启状态不能为空") | |
| 25 | + private Integer status; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "备注") | |
| 28 | + private String remark; | |
| 29 | + | |
| 30 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import javax.validation.constraints.*; | |
| 7 | + | |
| 8 | +@ApiModel("支付商户信息创建 Request VO") | |
| 9 | +@Data | |
| 10 | +@EqualsAndHashCode(callSuper = true) | |
| 11 | +@ToString(callSuper = true) | |
| 12 | +public class PayMerchantCreateReqVO extends PayMerchantBaseVO { | |
| 13 | + | |
| 14 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExcelVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 4 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 5 | +import com.alibaba.excel.annotation.ExcelProperty; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 支付商户信息 Excel VO | |
| 12 | + * | |
| 13 | + * @author 芋艿 | |
| 14 | + */ | |
| 15 | +@Data | |
| 16 | +public class PayMerchantExcelVO { | |
| 17 | + | |
| 18 | + @ExcelProperty("商户编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @ExcelProperty("商户号") | |
| 22 | + private String no; | |
| 23 | + | |
| 24 | + @ExcelProperty("商户全称") | |
| 25 | + private String name; | |
| 26 | + | |
| 27 | + @ExcelProperty("商户简称") | |
| 28 | + private String shortName; | |
| 29 | + | |
| 30 | + @ExcelProperty(value = "开启状态",converter = DictConvert.class) | |
| 31 | + @DictFormat("sys_common_status") | |
| 32 | + private Integer status; | |
| 33 | + | |
| 34 | + @ExcelProperty("备注") | |
| 35 | + private String remark; | |
| 36 | + | |
| 37 | + @ExcelProperty("创建时间") | |
| 38 | + private Date createTime; | |
| 39 | + | |
| 40 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExportReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | + | |
| 11 | +@ApiModel(value = "支付商户信息 Excel 导出 Request VO", description = "参数和 PayMerchantPageReqVO 是一致的") | |
| 12 | +@Data | |
| 13 | +public class PayMerchantExportReqVO { | |
| 14 | + | |
| 15 | + @ApiModelProperty(value = "商户号") | |
| 16 | + private String no; | |
| 17 | + | |
| 18 | + @ApiModelProperty(value = "商户全称") | |
| 19 | + private String name; | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "商户简称") | |
| 22 | + private String shortName; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "开启状态") | |
| 25 | + private Integer status; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "备注") | |
| 28 | + private String remark; | |
| 29 | + | |
| 30 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 31 | + @ApiModelProperty(value = "开始创建时间") | |
| 32 | + private Date beginCreateTime; | |
| 33 | + | |
| 34 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 35 | + @ApiModelProperty(value = "结束创建时间") | |
| 36 | + private Date endCreateTime; | |
| 37 | + | |
| 38 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | + | |
| 11 | +@ApiModel("支付商户信息分页 Request VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class PayMerchantPageReqVO extends PageParam { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "商户号") | |
| 18 | + private String no; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "商户全称") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "商户简称") | |
| 24 | + private String shortName; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "开启状态") | |
| 27 | + private Integer status; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "备注") | |
| 30 | + private String remark; | |
| 31 | + | |
| 32 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 33 | + @ApiModelProperty(value = "开始创建时间") | |
| 34 | + private Date beginCreateTime; | |
| 35 | + | |
| 36 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 37 | + @ApiModelProperty(value = "结束创建时间") | |
| 38 | + private Date endCreateTime; | |
| 39 | + | |
| 40 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +@ApiModel("支付商户信息 Response VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class PayMerchantRespVO extends PayMerchantBaseVO { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 18 | + private Long id; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 21 | + private Date createTime; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 商户号 | |
| 25 | + * 例如说,M233666999 | |
| 26 | + * 只有新增时插入,不允许修改 | |
| 27 | + */ | |
| 28 | + private String no; | |
| 29 | + | |
| 30 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.annotations.*; | |
| 6 | +import javax.validation.constraints.*; | |
| 7 | + | |
| 8 | +@ApiModel("支付商户信息更新 Request VO") | |
| 9 | +@Data | |
| 10 | +@EqualsAndHashCode(callSuper = true) | |
| 11 | +@ToString(callSuper = true) | |
| 12 | +public class PayMerchantUpdateReqVO extends PayMerchantBaseVO { | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 15 | + @NotNull(message = "商户编号不能为空") | |
| 16 | + private Long id; | |
| 17 | + | |
| 18 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateStatusReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import javax.validation.constraints.NotNull; | |
| 8 | + | |
| 9 | +@ApiModel("商户更新状态 Request VO") | |
| 10 | +@Data | |
| 11 | +public class PayMerchantUpdateStatusReqVO { | |
| 12 | + | |
| 13 | + @ApiModelProperty(value = "商户编号", required = true, example = "1024") | |
| 14 | + @NotNull(message = "商户编号不能为空") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") | |
| 18 | + @NotNull(message = "状态不能为空") | |
| 19 | + private Integer status; | |
| 20 | + | |
| 21 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayOrderController.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollectionUtil; | |
| 4 | +import cn.hutool.core.util.ObjectUtil; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.*; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.order.PayOrderConvert; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderExtensionService; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 12 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 13 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 14 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; | |
| 15 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 16 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 17 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 18 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 19 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 20 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 21 | +import io.swagger.annotations.Api; | |
| 22 | +import io.swagger.annotations.ApiImplicitParam; | |
| 23 | +import io.swagger.annotations.ApiOperation; | |
| 24 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 25 | +import org.springframework.validation.annotation.Validated; | |
| 26 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 27 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 28 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 29 | +import org.springframework.web.bind.annotation.RestController; | |
| 30 | + | |
| 31 | +import javax.annotation.Resource; | |
| 32 | +import javax.servlet.http.HttpServletResponse; | |
| 33 | +import javax.validation.Valid; | |
| 34 | +import java.io.IOException; | |
| 35 | +import java.util.ArrayList; | |
| 36 | +import java.util.List; | |
| 37 | +import java.util.Map; | |
| 38 | + | |
| 39 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 40 | +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * 支付订单 controller 组件 | |
| 44 | + * | |
| 45 | + * @author aquan | |
| 46 | + */ | |
| 47 | +@Api(tags = "支付订单") | |
| 48 | +@RestController | |
| 49 | +@RequestMapping("/pay/order") | |
| 50 | +@Validated | |
| 51 | +public class PayOrderController { | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 订单 service 组件 | |
| 55 | + */ | |
| 56 | + @Resource | |
| 57 | + private PayOrderService orderService; | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * 订单扩展 service 组件 | |
| 61 | + */ | |
| 62 | + @Resource | |
| 63 | + private PayOrderExtensionService orderExtensionService; | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 商户 service 组件 | |
| 67 | + */ | |
| 68 | + @Resource | |
| 69 | + private PayMerchantService merchantService; | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * 应用 service 组件 | |
| 73 | + */ | |
| 74 | + @Resource | |
| 75 | + private PayAppService appService; | |
| 76 | + | |
| 77 | + @GetMapping("/get") | |
| 78 | + @ApiOperation("获得支付订单") | |
| 79 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | |
| 80 | + @PreAuthorize("@ss.hasPermission('pay:order:query')") | |
| 81 | + public CommonResult<PayOrderDetailsRespVO> getOrder(@RequestParam("id") Long id) { | |
| 82 | + PayOrderDO order = orderService.getOrder(id); | |
| 83 | + if (ObjectUtil.isNull(order)) { | |
| 84 | + return success(new PayOrderDetailsRespVO()); | |
| 85 | + } | |
| 86 | + | |
| 87 | + PayMerchantDO merchantDO = merchantService.getMerchant(order.getMerchantId()); | |
| 88 | + PayAppDO appDO = appService.getApp(order.getAppId()); | |
| 89 | + PayChannelEnum channelEnum = PayChannelEnum.getByCode(order.getChannelCode()); | |
| 90 | + | |
| 91 | + PayOrderDetailsRespVO respVO = PayOrderConvert.INSTANCE.orderDetailConvert(order); | |
| 92 | + respVO.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); | |
| 93 | + respVO.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | |
| 94 | + respVO.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | |
| 95 | + | |
| 96 | + PayOrderExtensionDO extensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); | |
| 97 | + if (ObjectUtil.isNotNull(extensionDO)) { | |
| 98 | + respVO.setPayOrderExtension(PayOrderConvert.INSTANCE.orderDetailExtensionConvert(extensionDO)); | |
| 99 | + } | |
| 100 | + | |
| 101 | + return success(respVO); | |
| 102 | + } | |
| 103 | + | |
| 104 | + @GetMapping("/page") | |
| 105 | + @ApiOperation("获得支付订单分页") | |
| 106 | + @PreAuthorize("@ss.hasPermission('pay:order:query')") | |
| 107 | + public CommonResult<PageResult<PayOrderPageItemRespVO>> getOrderPage(@Valid PayOrderPageReqVO pageVO) { | |
| 108 | + PageResult<PayOrderDO> pageResult = orderService.getOrderPage(pageVO); | |
| 109 | + if (CollectionUtil.isEmpty(pageResult.getList())) { | |
| 110 | + return success(new PageResult<>(pageResult.getTotal())); | |
| 111 | + } | |
| 112 | + | |
| 113 | + // 处理商户ID数据 | |
| 114 | + Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap( | |
| 115 | + CollectionUtils.convertList(pageResult.getList(), PayOrderDO::getMerchantId)); | |
| 116 | + // 处理应用ID数据 | |
| 117 | + Map<Long, PayAppDO> appMap = appService.getAppMap( | |
| 118 | + CollectionUtils.convertList(pageResult.getList(), PayOrderDO::getAppId)); | |
| 119 | + | |
| 120 | + List<PayOrderPageItemRespVO> pageList = new ArrayList<>(pageResult.getList().size()); | |
| 121 | + pageResult.getList().forEach(c -> { | |
| 122 | + PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId()); | |
| 123 | + PayAppDO appDO = appMap.get(c.getAppId()); | |
| 124 | + PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | |
| 125 | + | |
| 126 | + PayOrderPageItemRespVO orderItem = PayOrderConvert.INSTANCE.pageConvertItemPage(c); | |
| 127 | + orderItem.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); | |
| 128 | + orderItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | |
| 129 | + orderItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | |
| 130 | + pageList.add(orderItem); | |
| 131 | + }); | |
| 132 | + return success(new PageResult<>(pageList, pageResult.getTotal())); | |
| 133 | + } | |
| 134 | + | |
| 135 | + @GetMapping("/export-excel") | |
| 136 | + @ApiOperation("导出支付订单Excel") | |
| 137 | + @PreAuthorize("@ss.hasPermission('pay:order:export')") | |
| 138 | + @OperateLog(type = EXPORT) | |
| 139 | + public void exportOrderExcel(@Valid PayOrderExportReqVO exportReqVO, | |
| 140 | + HttpServletResponse response) throws IOException { | |
| 141 | + | |
| 142 | + List<PayOrderDO> list = orderService.getOrderList(exportReqVO); | |
| 143 | + if (CollectionUtil.isEmpty(list)) { | |
| 144 | + ExcelUtils.write(response, "支付订单.xls", "数据", | |
| 145 | + PayOrderExcelVO.class, new ArrayList<>()); | |
| 146 | + } | |
| 147 | + | |
| 148 | + // 处理商户ID数据 | |
| 149 | + Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap( | |
| 150 | + CollectionUtils.convertList(list, PayOrderDO::getMerchantId)); | |
| 151 | + // 处理应用ID数据 | |
| 152 | + Map<Long, PayAppDO> appMap = appService.getAppMap( | |
| 153 | + CollectionUtils.convertList(list, PayOrderDO::getAppId)); | |
| 154 | + // 处理扩展订单数据 | |
| 155 | + Map<Long, PayOrderExtensionDO> orderExtensionMap = orderExtensionService | |
| 156 | + .getOrderExtensionMap(CollectionUtils.convertList(list, PayOrderDO::getSuccessExtensionId)); | |
| 157 | + | |
| 158 | + List<PayOrderExcelVO> excelDatum = new ArrayList<>(list.size()); | |
| 159 | + list.forEach(c -> { | |
| 160 | + PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId()); | |
| 161 | + PayAppDO appDO = appMap.get(c.getAppId()); | |
| 162 | + PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | |
| 163 | + PayOrderExtensionDO orderExtensionDO = orderExtensionMap.get(c.getSuccessExtensionId()); | |
| 164 | + | |
| 165 | + PayOrderExcelVO excelItem = PayOrderConvert.INSTANCE.excelConvert(c); | |
| 166 | + excelItem.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); | |
| 167 | + excelItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | |
| 168 | + excelItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | |
| 169 | + excelItem.setNo(ObjectUtil.isNotNull(orderExtensionDO) ? orderExtensionDO.getNo() : ""); | |
| 170 | + excelDatum.add(excelItem); | |
| 171 | + }); | |
| 172 | + | |
| 173 | + // 导出 Excel | |
| 174 | + ExcelUtils.write(response, "支付订单.xls", "数据", PayOrderExcelVO.class, excelDatum); | |
| 175 | + } | |
| 176 | + | |
| 177 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayRefundController.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollectionUtil; | |
| 4 | +import cn.hutool.core.util.ObjectUtil; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.*; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.refund.PayRefundConvert; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayRefundService; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 12 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 13 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 14 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 15 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 16 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 17 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 18 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 19 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 20 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 21 | +import io.swagger.annotations.Api; | |
| 22 | +import io.swagger.annotations.ApiImplicitParam; | |
| 23 | +import io.swagger.annotations.ApiOperation; | |
| 24 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 25 | +import org.springframework.validation.annotation.Validated; | |
| 26 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 27 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 28 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 29 | +import org.springframework.web.bind.annotation.RestController; | |
| 30 | + | |
| 31 | +import javax.annotation.Resource; | |
| 32 | +import javax.servlet.http.HttpServletResponse; | |
| 33 | +import javax.validation.Valid; | |
| 34 | +import java.io.IOException; | |
| 35 | +import java.util.ArrayList; | |
| 36 | +import java.util.List; | |
| 37 | +import java.util.Map; | |
| 38 | + | |
| 39 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 40 | +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * 退款订单 Controller 组件 | |
| 44 | + * | |
| 45 | + * @author aquan | |
| 46 | + */ | |
| 47 | +@Api(tags = "退款订单") | |
| 48 | +@RestController | |
| 49 | +@RequestMapping("/pay/refund") | |
| 50 | +@Validated | |
| 51 | +public class PayRefundController { | |
| 52 | + | |
| 53 | + @Resource | |
| 54 | + private PayRefundService refundService; | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 商户 service 组件 | |
| 58 | + */ | |
| 59 | + @Resource | |
| 60 | + private PayMerchantService merchantService; | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 应用 service 组件 | |
| 64 | + */ | |
| 65 | + @Resource | |
| 66 | + private PayAppService appService; | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 订单 service 组件 | |
| 70 | + */ | |
| 71 | + @Resource | |
| 72 | + private PayOrderService orderService; | |
| 73 | + | |
| 74 | + | |
| 75 | + @GetMapping("/get") | |
| 76 | + @ApiOperation("获得退款订单") | |
| 77 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | |
| 78 | + @PreAuthorize("@ss.hasPermission('pay:refund:query')") | |
| 79 | + public CommonResult<PayRefundDetailsRespVO> getRefund(@RequestParam("id") Long id) { | |
| 80 | + PayRefundDO refund = refundService.getRefund(id); | |
| 81 | + if (ObjectUtil.isNull(refund)) { | |
| 82 | + return success(new PayRefundDetailsRespVO()); | |
| 83 | + } | |
| 84 | + | |
| 85 | + PayMerchantDO merchantDO = merchantService.getMerchant(refund.getMerchantId()); | |
| 86 | + PayAppDO appDO = appService.getApp(refund.getAppId()); | |
| 87 | + PayChannelEnum channelEnum = PayChannelEnum.getByCode(refund.getChannelCode()); | |
| 88 | + PayOrderDO orderDO = orderService.getOrder(refund.getOrderId()); | |
| 89 | + | |
| 90 | + PayRefundDetailsRespVO refundDetail = PayRefundConvert.INSTANCE.refundDetailConvert(refund); | |
| 91 | + refundDetail.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); | |
| 92 | + refundDetail.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | |
| 93 | + refundDetail.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | |
| 94 | + refundDetail.setSubject(orderDO.getSubject()); | |
| 95 | + | |
| 96 | + return success(refundDetail); | |
| 97 | + } | |
| 98 | + | |
| 99 | + @GetMapping("/page") | |
| 100 | + @ApiOperation("获得退款订单分页") | |
| 101 | + @PreAuthorize("@ss.hasPermission('pay:refund:query')") | |
| 102 | + public CommonResult<PageResult<PayRefundPageItemRespVO>> getRefundPage(@Valid PayRefundPageReqVO pageVO) { | |
| 103 | + PageResult<PayRefundDO> pageResult = refundService.getRefundPage(pageVO); | |
| 104 | + if (CollectionUtil.isEmpty(pageResult.getList())) { | |
| 105 | + return success(new PageResult<>(pageResult.getTotal())); | |
| 106 | + } | |
| 107 | + | |
| 108 | + // 处理商户ID数据 | |
| 109 | + Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap( | |
| 110 | + CollectionUtils.convertList(pageResult.getList(), PayRefundDO::getMerchantId)); | |
| 111 | + // 处理应用ID数据 | |
| 112 | + Map<Long, PayAppDO> appMap = appService.getAppMap( | |
| 113 | + CollectionUtils.convertList(pageResult.getList(), PayRefundDO::getAppId)); | |
| 114 | + List<PayRefundPageItemRespVO> list = new ArrayList<>(pageResult.getList().size()); | |
| 115 | + pageResult.getList().forEach(c -> { | |
| 116 | + PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId()); | |
| 117 | + PayAppDO appDO = appMap.get(c.getAppId()); | |
| 118 | + PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | |
| 119 | + | |
| 120 | + PayRefundPageItemRespVO item = PayRefundConvert.INSTANCE.pageItemConvert(c); | |
| 121 | + | |
| 122 | + item.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); | |
| 123 | + item.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | |
| 124 | + item.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | |
| 125 | + list.add(item); | |
| 126 | + }); | |
| 127 | + | |
| 128 | + return success(new PageResult<>(list, pageResult.getTotal())); | |
| 129 | + } | |
| 130 | + | |
| 131 | + @GetMapping("/export-excel") | |
| 132 | + @ApiOperation("导出退款订单 Excel") | |
| 133 | + @PreAuthorize("@ss.hasPermission('pay:refund:export')") | |
| 134 | + @OperateLog(type = EXPORT) | |
| 135 | + public void exportRefundExcel(@Valid PayRefundExportReqVO exportReqVO, | |
| 136 | + HttpServletResponse response) throws IOException { | |
| 137 | + | |
| 138 | + List<PayRefundDO> list = refundService.getRefundList(exportReqVO); | |
| 139 | + if (CollectionUtil.isEmpty(list)) { | |
| 140 | + ExcelUtils.write(response, "退款订单.xls", "数据", | |
| 141 | + PayRefundExcelVO.class, new ArrayList<>()); | |
| 142 | + } | |
| 143 | + | |
| 144 | + // 处理商户ID数据 | |
| 145 | + Map<Long, PayMerchantDO> merchantMap = merchantService.getMerchantMap( | |
| 146 | + CollectionUtils.convertList(list, PayRefundDO::getMerchantId)); | |
| 147 | + // 处理应用ID数据 | |
| 148 | + Map<Long, PayAppDO> appMap = appService.getAppMap( | |
| 149 | + CollectionUtils.convertList(list, PayRefundDO::getAppId)); | |
| 150 | + | |
| 151 | + List<PayRefundExcelVO> excelDatum = new ArrayList<>(list.size()); | |
| 152 | + // 处理商品名称数据 | |
| 153 | + Map<Long, PayOrderDO> orderMap = orderService.getOrderSubjectMap( | |
| 154 | + CollectionUtils.convertList(list, PayRefundDO::getOrderId)); | |
| 155 | + | |
| 156 | + list.forEach(c -> { | |
| 157 | + PayMerchantDO merchantDO = merchantMap.get(c.getMerchantId()); | |
| 158 | + PayAppDO appDO = appMap.get(c.getAppId()); | |
| 159 | + PayChannelEnum channelEnum = PayChannelEnum.getByCode(c.getChannelCode()); | |
| 160 | + | |
| 161 | + PayRefundExcelVO excelItem = PayRefundConvert.INSTANCE.excelConvert(c); | |
| 162 | + excelItem.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); | |
| 163 | + excelItem.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); | |
| 164 | + excelItem.setChannelCodeName(ObjectUtil.isNotNull(channelEnum) ? channelEnum.getName() : "未知渠道"); | |
| 165 | + excelItem.setSubject(orderMap.get(c.getOrderId()).getSubject()); | |
| 166 | + | |
| 167 | + excelDatum.add(excelItem); | |
| 168 | + }); | |
| 169 | + | |
| 170 | + // 导出 Excel | |
| 171 | + ExcelUtils.write(response, "退款订单.xls", "数据", PayRefundExcelVO.class, excelDatum); | |
| 172 | + } | |
| 173 | + | |
| 174 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderBaseVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModelProperty; | |
| 4 | +import lombok.Data; | |
| 5 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 6 | + | |
| 7 | +import javax.validation.constraints.NotNull; | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 支付订单 | |
| 14 | + * Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 15 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 16 | + * | |
| 17 | + * @author aquan | |
| 18 | + */ | |
| 19 | +@Data | |
| 20 | +public class PayOrderBaseVO { | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 23 | + @NotNull(message = "商户编号不能为空") | |
| 24 | + private Long merchantId; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "应用编号", required = true) | |
| 27 | + @NotNull(message = "应用编号不能为空") | |
| 28 | + private Long appId; | |
| 29 | + | |
| 30 | + @ApiModelProperty(value = "渠道编号") | |
| 31 | + private Long channelId; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "渠道编码") | |
| 34 | + private String channelCode; | |
| 35 | + | |
| 36 | + @ApiModelProperty(value = "商户订单编号", required = true) | |
| 37 | + @NotNull(message = "商户订单编号不能为空") | |
| 38 | + private String merchantOrderId; | |
| 39 | + | |
| 40 | + @ApiModelProperty(value = "商品标题", required = true) | |
| 41 | + @NotNull(message = "商品标题不能为空") | |
| 42 | + private String subject; | |
| 43 | + | |
| 44 | + @ApiModelProperty(value = "商品描述", required = true) | |
| 45 | + @NotNull(message = "商品描述不能为空") | |
| 46 | + private String body; | |
| 47 | + | |
| 48 | + @ApiModelProperty(value = "异步通知地址", required = true) | |
| 49 | + @NotNull(message = "异步通知地址不能为空") | |
| 50 | + private String notifyUrl; | |
| 51 | + | |
| 52 | + @ApiModelProperty(value = "通知商户支付结果的回调状态", required = true) | |
| 53 | + @NotNull(message = "通知商户支付结果的回调状态不能为空") | |
| 54 | + private Integer notifyStatus; | |
| 55 | + | |
| 56 | + @ApiModelProperty(value = "支付金额,单位:分", required = true) | |
| 57 | + @NotNull(message = "支付金额,单位:分不能为空") | |
| 58 | + private Long amount; | |
| 59 | + | |
| 60 | + @ApiModelProperty(value = "渠道手续费,单位:百分比") | |
| 61 | + private Double channelFeeRate; | |
| 62 | + | |
| 63 | + @ApiModelProperty(value = "渠道手续金额,单位:分") | |
| 64 | + private Long channelFeeAmount; | |
| 65 | + | |
| 66 | + @ApiModelProperty(value = "支付状态", required = true) | |
| 67 | + @NotNull(message = "支付状态不能为空") | |
| 68 | + private Integer status; | |
| 69 | + | |
| 70 | + @ApiModelProperty(value = "用户 IP", required = true) | |
| 71 | + @NotNull(message = "用户 IP不能为空") | |
| 72 | + private String userIp; | |
| 73 | + | |
| 74 | + @ApiModelProperty(value = "订单失效时间", required = true) | |
| 75 | + @NotNull(message = "订单失效时间不能为空") | |
| 76 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 77 | + private Date expireTime; | |
| 78 | + | |
| 79 | + @ApiModelProperty(value = "订单支付成功时间") | |
| 80 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 81 | + private Date successTime; | |
| 82 | + | |
| 83 | + @ApiModelProperty(value = "订单支付通知时间") | |
| 84 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 85 | + private Date notifyTime; | |
| 86 | + | |
| 87 | + @ApiModelProperty(value = "支付成功的订单拓展单编号") | |
| 88 | + private Long successExtensionId; | |
| 89 | + | |
| 90 | + @ApiModelProperty(value = "退款状态", required = true) | |
| 91 | + @NotNull(message = "退款状态不能为空") | |
| 92 | + private Integer refundStatus; | |
| 93 | + | |
| 94 | + @ApiModelProperty(value = "退款次数", required = true) | |
| 95 | + @NotNull(message = "退款次数不能为空") | |
| 96 | + private Integer refundTimes; | |
| 97 | + | |
| 98 | + @ApiModelProperty(value = "退款总金额,单位:分", required = true) | |
| 99 | + @NotNull(message = "退款总金额,单位:分不能为空") | |
| 100 | + private Long refundAmount; | |
| 101 | + | |
| 102 | + @ApiModelProperty(value = "渠道用户编号") | |
| 103 | + private String channelUserId; | |
| 104 | + | |
| 105 | + @ApiModelProperty(value = "渠道订单号") | |
| 106 | + private String channelOrderNo; | |
| 107 | + | |
| 108 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderDetailsRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 支付订单详细信息,由支付订单和支付订单扩展信息组成 | |
| 13 | + * | |
| 14 | + * @author aquan | |
| 15 | + */ | |
| 16 | +@ApiModel("支付订单详细信息 Response VO") | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +public class PayOrderDetailsRespVO extends PayOrderBaseVO { | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "支付订单编号") | |
| 23 | + private Long id; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "商户名称") | |
| 26 | + private String merchantName; | |
| 27 | + | |
| 28 | + @ApiModelProperty(value = "应用名称") | |
| 29 | + private String appName; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "渠道编号名称") | |
| 32 | + private String channelCodeName; | |
| 33 | + | |
| 34 | + @ApiModelProperty(value = "创建时间") | |
| 35 | + private Date createTime; | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * 支付订单扩展 | |
| 39 | + */ | |
| 40 | + private PayOrderExtension payOrderExtension; | |
| 41 | + | |
| 42 | + @Data | |
| 43 | + @ApiModel("支付订单扩展") | |
| 44 | + public static class PayOrderExtension { | |
| 45 | + | |
| 46 | + @ApiModelProperty(value = "支付订单号") | |
| 47 | + private String no; | |
| 48 | + | |
| 49 | + @ApiModelProperty(value = "支付异步通知的内容") | |
| 50 | + private String channelNotifyData; | |
| 51 | + } | |
| 52 | + | |
| 53 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExcelVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; | |
| 4 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 5 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 6 | +import com.alibaba.excel.annotation.ExcelProperty; | |
| 7 | +import lombok.Data; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 支付订单Excel VO | |
| 13 | + * | |
| 14 | + * @author aquan | |
| 15 | + */ | |
| 16 | +@Data | |
| 17 | +public class PayOrderExcelVO { | |
| 18 | + | |
| 19 | + @ExcelProperty("支付订单编号") | |
| 20 | + private Long id; | |
| 21 | + | |
| 22 | + @ExcelProperty(value = "商户名称") | |
| 23 | + private String merchantName; | |
| 24 | + | |
| 25 | + @ExcelProperty(value = "应用名称") | |
| 26 | + private String appName; | |
| 27 | + | |
| 28 | + @ExcelProperty("商品标题") | |
| 29 | + private String subject; | |
| 30 | + | |
| 31 | + @ExcelProperty("商户订单编号") | |
| 32 | + private String merchantOrderId; | |
| 33 | + | |
| 34 | + @ExcelProperty("渠道订单号") | |
| 35 | + private String channelOrderNo; | |
| 36 | + | |
| 37 | + @ExcelProperty(value = "支付订单号") | |
| 38 | + private String no; | |
| 39 | + | |
| 40 | + @ExcelProperty("支付金额,单位:元") | |
| 41 | + private String amount; | |
| 42 | + | |
| 43 | + @ExcelProperty("渠道手续金额,单位:元") | |
| 44 | + private String channelFeeAmount; | |
| 45 | + | |
| 46 | + @ExcelProperty("渠道手续费,单位:百分比") | |
| 47 | + private String channelFeeRate; | |
| 48 | + | |
| 49 | + @DictFormat(SysDictTypeConstants.PAY_ORDER_STATUS) | |
| 50 | + @ExcelProperty(value = "支付状态", converter = DictConvert.class) | |
| 51 | + private Integer status; | |
| 52 | + | |
| 53 | + @DictFormat(SysDictTypeConstants.PAY_ORDER_NOTIFY_STATUS) | |
| 54 | + @ExcelProperty(value = "通知商户支付结果的回调状态", converter = DictConvert.class) | |
| 55 | + private Integer notifyStatus; | |
| 56 | + | |
| 57 | + @ExcelProperty("异步通知地址") | |
| 58 | + private String notifyUrl; | |
| 59 | + | |
| 60 | + @ExcelProperty("创建时间") | |
| 61 | + private Date createTime; | |
| 62 | + | |
| 63 | + @ExcelProperty("订单支付成功时间") | |
| 64 | + private Date successTime; | |
| 65 | + | |
| 66 | + @ExcelProperty("订单失效时间") | |
| 67 | + private Date expireTime; | |
| 68 | + | |
| 69 | + @ExcelProperty("订单支付通知时间") | |
| 70 | + private Date notifyTime; | |
| 71 | + | |
| 72 | + @ExcelProperty(value = "渠道编号名称") | |
| 73 | + private String channelCodeName; | |
| 74 | + | |
| 75 | + @ExcelProperty("用户 IP") | |
| 76 | + private String userIp; | |
| 77 | + | |
| 78 | + @DictFormat(SysDictTypeConstants.PAY_ORDER_REFUND_STATUS) | |
| 79 | + @ExcelProperty(value = "退款状态", converter = DictConvert.class) | |
| 80 | + private Integer refundStatus; | |
| 81 | + | |
| 82 | + @ExcelProperty("退款次数") | |
| 83 | + private Integer refundTimes; | |
| 84 | + | |
| 85 | + @ExcelProperty("退款总金额,单位:元") | |
| 86 | + private String refundAmount; | |
| 87 | + | |
| 88 | + @ExcelProperty("商品描述") | |
| 89 | + private String body; | |
| 90 | + | |
| 91 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExportReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | + | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 支付订单 Excel 导出 Request VO | |
| 14 | + * @author aquan | |
| 15 | + */ | |
| 16 | +@ApiModel(value = "支付订单 Excel 导出 Request VO", description = "参数和 PayOrderPageReqVO 是一致的") | |
| 17 | +@Data | |
| 18 | +public class PayOrderExportReqVO { | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "商户编号") | |
| 21 | + private Long merchantId; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "应用编号") | |
| 24 | + private Long appId; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "渠道编号") | |
| 27 | + private Long channelId; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "渠道编码") | |
| 30 | + private String channelCode; | |
| 31 | + | |
| 32 | + @ApiModelProperty(value = "商户订单编号") | |
| 33 | + private String merchantOrderId; | |
| 34 | + | |
| 35 | + @ApiModelProperty(value = "商品标题") | |
| 36 | + private String subject; | |
| 37 | + | |
| 38 | + @ApiModelProperty(value = "商品描述") | |
| 39 | + private String body; | |
| 40 | + | |
| 41 | + @ApiModelProperty(value = "异步通知地址") | |
| 42 | + private String notifyUrl; | |
| 43 | + | |
| 44 | + @ApiModelProperty(value = "通知商户支付结果的回调状态") | |
| 45 | + private Integer notifyStatus; | |
| 46 | + | |
| 47 | + @ApiModelProperty(value = "支付金额,单位:分") | |
| 48 | + private Long amount; | |
| 49 | + | |
| 50 | + @ApiModelProperty(value = "渠道手续费,单位:百分比") | |
| 51 | + private Double channelFeeRate; | |
| 52 | + | |
| 53 | + @ApiModelProperty(value = "渠道手续金额,单位:分") | |
| 54 | + private Long channelFeeAmount; | |
| 55 | + | |
| 56 | + @ApiModelProperty(value = "支付状态") | |
| 57 | + private Integer status; | |
| 58 | + | |
| 59 | + @ApiModelProperty(value = "用户 IP") | |
| 60 | + private String userIp; | |
| 61 | + | |
| 62 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 63 | + @ApiModelProperty(value = "开始订单失效时间") | |
| 64 | + private Date beginExpireTime; | |
| 65 | + | |
| 66 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 67 | + @ApiModelProperty(value = "结束订单失效时间") | |
| 68 | + private Date endExpireTime; | |
| 69 | + | |
| 70 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 71 | + @ApiModelProperty(value = "开始订单支付成功时间") | |
| 72 | + private Date beginSuccessTime; | |
| 73 | + | |
| 74 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 75 | + @ApiModelProperty(value = "结束订单支付成功时间") | |
| 76 | + private Date endSuccessTime; | |
| 77 | + | |
| 78 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 79 | + @ApiModelProperty(value = "开始订单支付通知时间") | |
| 80 | + private Date beginNotifyTime; | |
| 81 | + | |
| 82 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 83 | + @ApiModelProperty(value = "结束订单支付通知时间") | |
| 84 | + private Date endNotifyTime; | |
| 85 | + | |
| 86 | + @ApiModelProperty(value = "支付成功的订单拓展单编号") | |
| 87 | + private Long successExtensionId; | |
| 88 | + | |
| 89 | + @ApiModelProperty(value = "退款状态") | |
| 90 | + private Integer refundStatus; | |
| 91 | + | |
| 92 | + @ApiModelProperty(value = "退款次数") | |
| 93 | + private Integer refundTimes; | |
| 94 | + | |
| 95 | + @ApiModelProperty(value = "退款总金额,单位:分") | |
| 96 | + private Long refundAmount; | |
| 97 | + | |
| 98 | + @ApiModelProperty(value = "渠道用户编号") | |
| 99 | + private String channelUserId; | |
| 100 | + | |
| 101 | + @ApiModelProperty(value = "渠道订单号") | |
| 102 | + private String channelOrderNo; | |
| 103 | + | |
| 104 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 105 | + @ApiModelProperty(value = "开始创建时间") | |
| 106 | + private Date beginCreateTime; | |
| 107 | + | |
| 108 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 109 | + @ApiModelProperty(value = "结束创建时间") | |
| 110 | + private Date endCreateTime; | |
| 111 | + | |
| 112 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageItemRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 支付订单分页 Request VO | |
| 13 | + * | |
| 14 | + * @author aquan | |
| 15 | + */ | |
| 16 | +@ApiModel("支付订单分页 Request VO") | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +public class PayOrderPageItemRespVO extends PayOrderBaseVO { | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "支付订单编号", required = true) | |
| 23 | + private Long id; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 26 | + private Date createTime; | |
| 27 | + | |
| 28 | + @ApiModelProperty(value = "商户名称") | |
| 29 | + private String merchantName; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "应用名称") | |
| 32 | + private String appName; | |
| 33 | + | |
| 34 | + @ApiModelProperty(value = "渠道名称") | |
| 35 | + private String channelCodeName; | |
| 36 | + | |
| 37 | + @ApiModelProperty(value = "支付订单号") | |
| 38 | + private String no; | |
| 39 | + | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | +import io.swagger.annotations.ApiModel; | |
| 5 | +import io.swagger.annotations.ApiModelProperty; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.EqualsAndHashCode; | |
| 8 | +import lombok.ToString; | |
| 9 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 10 | + | |
| 11 | +import java.util.Date; | |
| 12 | + | |
| 13 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 支付订单分页 Request VO | |
| 17 | + * | |
| 18 | + * @author aquan | |
| 19 | + */ | |
| 20 | +@ApiModel("支付订单分页 Request VO") | |
| 21 | +@Data | |
| 22 | +@EqualsAndHashCode(callSuper = true) | |
| 23 | +@ToString(callSuper = true) | |
| 24 | +public class PayOrderPageReqVO extends PageParam { | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "商户编号") | |
| 27 | + private Long merchantId; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "应用编号") | |
| 30 | + private Long appId; | |
| 31 | + | |
| 32 | + @ApiModelProperty(value = "渠道编号") | |
| 33 | + private Long channelId; | |
| 34 | + | |
| 35 | + @ApiModelProperty(value = "渠道编码") | |
| 36 | + private String channelCode; | |
| 37 | + | |
| 38 | + @ApiModelProperty(value = "商户订单编号") | |
| 39 | + private String merchantOrderId; | |
| 40 | + | |
| 41 | + @ApiModelProperty(value = "商品标题") | |
| 42 | + private String subject; | |
| 43 | + | |
| 44 | + @ApiModelProperty(value = "商品描述") | |
| 45 | + private String body; | |
| 46 | + | |
| 47 | + @ApiModelProperty(value = "异步通知地址") | |
| 48 | + private String notifyUrl; | |
| 49 | + | |
| 50 | + @ApiModelProperty(value = "通知商户支付结果的回调状态") | |
| 51 | + private Integer notifyStatus; | |
| 52 | + | |
| 53 | + @ApiModelProperty(value = "支付金额,单位:分") | |
| 54 | + private Long amount; | |
| 55 | + | |
| 56 | + @ApiModelProperty(value = "渠道手续费,单位:百分比") | |
| 57 | + private Double channelFeeRate; | |
| 58 | + | |
| 59 | + @ApiModelProperty(value = "渠道手续金额,单位:分") | |
| 60 | + private Long channelFeeAmount; | |
| 61 | + | |
| 62 | + @ApiModelProperty(value = "支付状态") | |
| 63 | + private Integer status; | |
| 64 | + | |
| 65 | + @ApiModelProperty(value = "用户 IP") | |
| 66 | + private String userIp; | |
| 67 | + | |
| 68 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 69 | + @ApiModelProperty(value = "开始订单失效时间") | |
| 70 | + private Date beginExpireTime; | |
| 71 | + | |
| 72 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 73 | + @ApiModelProperty(value = "结束订单失效时间") | |
| 74 | + private Date endExpireTime; | |
| 75 | + | |
| 76 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 77 | + @ApiModelProperty(value = "开始订单支付成功时间") | |
| 78 | + private Date beginSuccessTime; | |
| 79 | + | |
| 80 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 81 | + @ApiModelProperty(value = "结束订单支付成功时间") | |
| 82 | + private Date endSuccessTime; | |
| 83 | + | |
| 84 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 85 | + @ApiModelProperty(value = "开始订单支付通知时间") | |
| 86 | + private Date beginNotifyTime; | |
| 87 | + | |
| 88 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 89 | + @ApiModelProperty(value = "结束订单支付通知时间") | |
| 90 | + private Date endNotifyTime; | |
| 91 | + | |
| 92 | + @ApiModelProperty(value = "支付成功的订单拓展单编号") | |
| 93 | + private Long successExtensionId; | |
| 94 | + | |
| 95 | + @ApiModelProperty(value = "退款状态") | |
| 96 | + private Integer refundStatus; | |
| 97 | + | |
| 98 | + @ApiModelProperty(value = "退款次数") | |
| 99 | + private Integer refundTimes; | |
| 100 | + | |
| 101 | + @ApiModelProperty(value = "退款总金额,单位:分") | |
| 102 | + private Long refundAmount; | |
| 103 | + | |
| 104 | + @ApiModelProperty(value = "渠道用户编号") | |
| 105 | + private String channelUserId; | |
| 106 | + | |
| 107 | + @ApiModelProperty(value = "渠道订单号") | |
| 108 | + private String channelOrderNo; | |
| 109 | + | |
| 110 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 111 | + @ApiModelProperty(value = "开始创建时间") | |
| 112 | + private Date beginCreateTime; | |
| 113 | + | |
| 114 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 115 | + @ApiModelProperty(value = "结束创建时间") | |
| 116 | + private Date endCreateTime; | |
| 117 | + | |
| 118 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 支付订单 Response VO | |
| 13 | + * | |
| 14 | + * @author aquan | |
| 15 | + */ | |
| 16 | +@ApiModel("支付订单 Response VO") | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +public class PayOrderRespVO extends PayOrderBaseVO { | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "支付订单编号", required = true) | |
| 23 | + private Long id; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 26 | + private Date createTime; | |
| 27 | + | |
| 28 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundBaseVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModelProperty; | |
| 4 | +import lombok.Data; | |
| 5 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 6 | + | |
| 7 | +import javax.validation.constraints.NotNull; | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +/** | |
| 13 | +* 退款订单 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 14 | +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 15 | +*/ | |
| 16 | +@Data | |
| 17 | +public class PayRefundBaseVO { | |
| 18 | + | |
| 19 | + @ApiModelProperty(value = "商户编号", required = true) | |
| 20 | + @NotNull(message = "商户编号不能为空") | |
| 21 | + private Long merchantId; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "应用编号", required = true) | |
| 24 | + @NotNull(message = "应用编号不能为空") | |
| 25 | + private Long appId; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "渠道编号", required = true) | |
| 28 | + @NotNull(message = "渠道编号不能为空") | |
| 29 | + private Long channelId; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "渠道编码", required = true) | |
| 32 | + @NotNull(message = "渠道编码不能为空") | |
| 33 | + private String channelCode; | |
| 34 | + | |
| 35 | + @ApiModelProperty(value = "支付订单编号 pay_order 表id", required = true) | |
| 36 | + @NotNull(message = "支付订单编号 pay_order 表id不能为空") | |
| 37 | + private Long orderId; | |
| 38 | + | |
| 39 | + @ApiModelProperty(value = "交易订单号 pay_extension 表no 字段", required = true) | |
| 40 | + @NotNull(message = "交易订单号 pay_extension 表no 字段不能为空") | |
| 41 | + private String tradeNo; | |
| 42 | + | |
| 43 | + @ApiModelProperty(value = "商户订单编号(商户系统生成)", required = true) | |
| 44 | + @NotNull(message = "商户订单编号(商户系统生成)不能为空") | |
| 45 | + private String merchantOrderId; | |
| 46 | + | |
| 47 | + @ApiModelProperty(value = "商户退款订单号(商户系统生成)", required = true) | |
| 48 | + @NotNull(message = "商户退款订单号(商户系统生成)不能为空") | |
| 49 | + private String merchantRefundNo; | |
| 50 | + | |
| 51 | + @ApiModelProperty(value = "异步通知商户地址", required = true) | |
| 52 | + @NotNull(message = "异步通知商户地址不能为空") | |
| 53 | + private String notifyUrl; | |
| 54 | + | |
| 55 | + @ApiModelProperty(value = "通知商户退款结果的回调状态", required = true) | |
| 56 | + @NotNull(message = "通知商户退款结果的回调状态不能为空") | |
| 57 | + private Integer notifyStatus; | |
| 58 | + | |
| 59 | + @ApiModelProperty(value = "退款状态", required = true) | |
| 60 | + @NotNull(message = "退款状态不能为空") | |
| 61 | + private Integer status; | |
| 62 | + | |
| 63 | + @ApiModelProperty(value = "退款类型(部分退款,全部退款)", required = true) | |
| 64 | + @NotNull(message = "退款类型(部分退款,全部退款)不能为空") | |
| 65 | + private Integer type; | |
| 66 | + | |
| 67 | + @ApiModelProperty(value = "支付金额,单位分", required = true) | |
| 68 | + @NotNull(message = "支付金额,单位分不能为空") | |
| 69 | + private Long payAmount; | |
| 70 | + | |
| 71 | + @ApiModelProperty(value = "退款金额,单位分", required = true) | |
| 72 | + @NotNull(message = "退款金额,单位分不能为空") | |
| 73 | + private Long refundAmount; | |
| 74 | + | |
| 75 | + @ApiModelProperty(value = "退款原因", required = true) | |
| 76 | + @NotNull(message = "退款原因不能为空") | |
| 77 | + private String reason; | |
| 78 | + | |
| 79 | + @ApiModelProperty(value = "用户 IP") | |
| 80 | + private String userIp; | |
| 81 | + | |
| 82 | + @ApiModelProperty(value = "渠道订单号,pay_order 中的channel_order_no 对应", required = true) | |
| 83 | + @NotNull(message = "渠道订单号,pay_order 中的channel_order_no 对应不能为空") | |
| 84 | + private String channelOrderNo; | |
| 85 | + | |
| 86 | + @ApiModelProperty(value = "渠道退款单号,渠道返回") | |
| 87 | + private String channelRefundNo; | |
| 88 | + | |
| 89 | + @ApiModelProperty(value = "渠道调用报错时,错误码") | |
| 90 | + private String channelErrorCode; | |
| 91 | + | |
| 92 | + @ApiModelProperty(value = "渠道调用报错时,错误信息") | |
| 93 | + private String channelErrorMsg; | |
| 94 | + | |
| 95 | + @ApiModelProperty(value = "支付渠道的额外参数") | |
| 96 | + private String channelExtras; | |
| 97 | + | |
| 98 | + @ApiModelProperty(value = "退款失效时间") | |
| 99 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 100 | + private Date expireTime; | |
| 101 | + | |
| 102 | + @ApiModelProperty(value = "退款成功时间") | |
| 103 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 104 | + private Date successTime; | |
| 105 | + | |
| 106 | + @ApiModelProperty(value = "退款通知时间") | |
| 107 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 108 | + private Date notifyTime; | |
| 109 | + | |
| 110 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundCreateReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import io.swagger.annotations.*; | |
| 5 | + | |
| 6 | +@ApiModel("退款订单创建 Request VO") | |
| 7 | +@Data | |
| 8 | +@EqualsAndHashCode(callSuper = true) | |
| 9 | +@ToString(callSuper = true) | |
| 10 | +public class PayRefundCreateReqVO extends PayRefundBaseVO { | |
| 11 | + | |
| 12 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundDetailsRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import javax.validation.constraints.NotNull; | |
| 10 | +import java.util.Date; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 退款订单详情 Response VO | |
| 14 | + * | |
| 15 | + * @author aquan | |
| 16 | + */ | |
| 17 | +@ApiModel("退款订单详情 Response VO") | |
| 18 | +@Data | |
| 19 | +@EqualsAndHashCode(callSuper = true) | |
| 20 | +@ToString(callSuper = true) | |
| 21 | +public class PayRefundDetailsRespVO extends PayRefundBaseVO { | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "支付退款编号", required = true) | |
| 24 | + private Long id; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "商户名称") | |
| 27 | + private String merchantName; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "应用名称") | |
| 30 | + private String appName; | |
| 31 | + | |
| 32 | + @ApiModelProperty(value = "渠道编号名称") | |
| 33 | + private String channelCodeName; | |
| 34 | + | |
| 35 | + @NotNull(message = "商品标题不能为空") | |
| 36 | + private String subject; | |
| 37 | + | |
| 38 | + @ApiModelProperty(value = "创建时间") | |
| 39 | + private Date createTime; | |
| 40 | + | |
| 41 | + @ApiModelProperty(value = "更新时间") | |
| 42 | + private Date updateTime; | |
| 43 | + | |
| 44 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExcelVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; | |
| 4 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 5 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 6 | +import com.alibaba.excel.annotation.ExcelProperty; | |
| 7 | +import lombok.Data; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 退款订单 Excel VO | |
| 13 | + * | |
| 14 | + * @author aquan | |
| 15 | + */ | |
| 16 | +@Data | |
| 17 | +public class PayRefundExcelVO { | |
| 18 | + | |
| 19 | + @ExcelProperty("支付退款编号") | |
| 20 | + private Long id; | |
| 21 | + | |
| 22 | + @ExcelProperty("商品名称") | |
| 23 | + private String subject; | |
| 24 | + | |
| 25 | + @ExcelProperty(value = "商户名称") | |
| 26 | + private String merchantName; | |
| 27 | + | |
| 28 | + @ExcelProperty(value = "应用名称") | |
| 29 | + private String appName; | |
| 30 | + | |
| 31 | + @ExcelProperty(value = "渠道编号名称") | |
| 32 | + private String channelCodeName; | |
| 33 | + | |
| 34 | + @ExcelProperty("交易订单号") | |
| 35 | + private String tradeNo; | |
| 36 | + | |
| 37 | + @ExcelProperty("商户订单编号") | |
| 38 | + private String merchantOrderId; | |
| 39 | + | |
| 40 | + @ExcelProperty("商户退款订单号") | |
| 41 | + private String merchantRefundNo; | |
| 42 | + | |
| 43 | + @ExcelProperty("异步通知商户地址") | |
| 44 | + private String notifyUrl; | |
| 45 | + | |
| 46 | + @DictFormat(SysDictTypeConstants.PAY_ORDER_NOTIFY_STATUS) | |
| 47 | + @ExcelProperty(value = "商户退款结果回调状态", converter = DictConvert.class) | |
| 48 | + private Integer notifyStatus; | |
| 49 | + | |
| 50 | + @DictFormat(SysDictTypeConstants.PAY_REFUND_ORDER_STATUS) | |
| 51 | + @ExcelProperty(value = "退款状态", converter = DictConvert.class) | |
| 52 | + private Integer status; | |
| 53 | + | |
| 54 | + @DictFormat(SysDictTypeConstants.PAY_REFUND_ORDER_TYPE) | |
| 55 | + @ExcelProperty(value = "退款类型", converter = DictConvert.class) | |
| 56 | + private Integer type; | |
| 57 | + | |
| 58 | + @ExcelProperty("支付金额,单位:元") | |
| 59 | + private String payAmount; | |
| 60 | + | |
| 61 | + @ExcelProperty("退款金额,单位:元") | |
| 62 | + private String refundAmount; | |
| 63 | + | |
| 64 | + @ExcelProperty("退款原因") | |
| 65 | + private String reason; | |
| 66 | + | |
| 67 | + @ExcelProperty("用户付款 IP") | |
| 68 | + private String userIp; | |
| 69 | + | |
| 70 | + @ExcelProperty("渠道订单号") | |
| 71 | + private String channelOrderNo; | |
| 72 | + | |
| 73 | + @ExcelProperty("渠道退款单号") | |
| 74 | + private String channelRefundNo; | |
| 75 | + | |
| 76 | + @ExcelProperty("创建时间") | |
| 77 | + private Date createTime; | |
| 78 | + | |
| 79 | + @ExcelProperty("退款成功时间") | |
| 80 | + private Date successTime; | |
| 81 | + | |
| 82 | + @ExcelProperty("退款通知时间") | |
| 83 | + private Date notifyTime; | |
| 84 | + | |
| 85 | + @ExcelProperty("退款失效时间") | |
| 86 | + private Date expireTime; | |
| 87 | + | |
| 88 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExportReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | + | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +@ApiModel(value = "退款订单 Excel 导出 Request VO", description = "参数和 PayRefundPageReqVO 是一致的") | |
| 13 | +@Data | |
| 14 | +public class PayRefundExportReqVO { | |
| 15 | + | |
| 16 | + @ApiModelProperty(value = "商户编号") | |
| 17 | + private Long merchantId; | |
| 18 | + | |
| 19 | + @ApiModelProperty(value = "应用编号") | |
| 20 | + private Long appId; | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "渠道编号") | |
| 23 | + private Long channelId; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "渠道编码") | |
| 26 | + private String channelCode; | |
| 27 | + | |
| 28 | + @ApiModelProperty(value = "支付订单编号 pay_order 表id") | |
| 29 | + private Long orderId; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "交易订单号 pay_extension 表no 字段") | |
| 32 | + private String tradeNo; | |
| 33 | + | |
| 34 | + @ApiModelProperty(value = "商户订单编号(商户系统生成)") | |
| 35 | + private String merchantOrderId; | |
| 36 | + | |
| 37 | + @ApiModelProperty(value = "商户退款订单号(商户系统生成)") | |
| 38 | + private String merchantRefundNo; | |
| 39 | + | |
| 40 | + @ApiModelProperty(value = "异步通知商户地址") | |
| 41 | + private String notifyUrl; | |
| 42 | + | |
| 43 | + @ApiModelProperty(value = "通知商户退款结果的回调状态") | |
| 44 | + private Integer notifyStatus; | |
| 45 | + | |
| 46 | + @ApiModelProperty(value = "退款状态") | |
| 47 | + private Integer status; | |
| 48 | + | |
| 49 | + @ApiModelProperty(value = "退款类型(部分退款,全部退款)") | |
| 50 | + private Integer type; | |
| 51 | + | |
| 52 | + @ApiModelProperty(value = "支付金额,单位分") | |
| 53 | + private Long payAmount; | |
| 54 | + | |
| 55 | + @ApiModelProperty(value = "退款金额,单位分") | |
| 56 | + private Long refundAmount; | |
| 57 | + | |
| 58 | + @ApiModelProperty(value = "退款原因") | |
| 59 | + private String reason; | |
| 60 | + | |
| 61 | + @ApiModelProperty(value = "用户 IP") | |
| 62 | + private String userIp; | |
| 63 | + | |
| 64 | + @ApiModelProperty(value = "渠道订单号,pay_order 中的channel_order_no 对应") | |
| 65 | + private String channelOrderNo; | |
| 66 | + | |
| 67 | + @ApiModelProperty(value = "渠道退款单号,渠道返回") | |
| 68 | + private String channelRefundNo; | |
| 69 | + | |
| 70 | + @ApiModelProperty(value = "渠道调用报错时,错误码") | |
| 71 | + private String channelErrorCode; | |
| 72 | + | |
| 73 | + @ApiModelProperty(value = "渠道调用报错时,错误信息") | |
| 74 | + private String channelErrorMsg; | |
| 75 | + | |
| 76 | + @ApiModelProperty(value = "支付渠道的额外参数") | |
| 77 | + private String channelExtras; | |
| 78 | + | |
| 79 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 80 | + @ApiModelProperty(value = "开始退款失效时间") | |
| 81 | + private Date beginExpireTime; | |
| 82 | + | |
| 83 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 84 | + @ApiModelProperty(value = "结束退款失效时间") | |
| 85 | + private Date endExpireTime; | |
| 86 | + | |
| 87 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 88 | + @ApiModelProperty(value = "开始退款成功时间") | |
| 89 | + private Date beginSuccessTime; | |
| 90 | + | |
| 91 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 92 | + @ApiModelProperty(value = "结束退款成功时间") | |
| 93 | + private Date endSuccessTime; | |
| 94 | + | |
| 95 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 96 | + @ApiModelProperty(value = "开始退款通知时间") | |
| 97 | + private Date beginNotifyTime; | |
| 98 | + | |
| 99 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 100 | + @ApiModelProperty(value = "结束退款通知时间") | |
| 101 | + private Date endNotifyTime; | |
| 102 | + | |
| 103 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 104 | + @ApiModelProperty(value = "开始创建时间") | |
| 105 | + private Date beginCreateTime; | |
| 106 | + | |
| 107 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 108 | + @ApiModelProperty(value = "结束创建时间") | |
| 109 | + private Date endCreateTime; | |
| 110 | + | |
| 111 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageItemRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 退款订单分页查询 Response VO | |
| 13 | + * @author aquan | |
| 14 | + */ | |
| 15 | +@ApiModel("退款订单分页查询 Response VO") | |
| 16 | +@Data | |
| 17 | +@EqualsAndHashCode(callSuper = true) | |
| 18 | +@ToString(callSuper = true) | |
| 19 | +public class PayRefundPageItemRespVO extends PayRefundBaseVO { | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "支付订单编号", required = true) | |
| 22 | + private Long id; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "商户名称") | |
| 25 | + private String merchantName; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "应用名称") | |
| 28 | + private String appName; | |
| 29 | + | |
| 30 | + @ApiModelProperty(value = "渠道名称") | |
| 31 | + private String channelCodeName; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 34 | + private Date createTime; | |
| 35 | + | |
| 36 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | +import io.swagger.annotations.ApiModel; | |
| 5 | +import io.swagger.annotations.ApiModelProperty; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.EqualsAndHashCode; | |
| 8 | +import lombok.ToString; | |
| 9 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 10 | + | |
| 11 | +import java.util.Date; | |
| 12 | + | |
| 13 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 14 | + | |
| 15 | +@ApiModel("退款订单分页 Request VO") | |
| 16 | +@Data | |
| 17 | +@EqualsAndHashCode(callSuper = true) | |
| 18 | +@ToString(callSuper = true) | |
| 19 | +public class PayRefundPageReqVO extends PageParam { | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "商户编号") | |
| 22 | + private Long merchantId; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "应用编号") | |
| 25 | + private Long appId; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "渠道编号") | |
| 28 | + private Long channelId; | |
| 29 | + | |
| 30 | + @ApiModelProperty(value = "渠道编码") | |
| 31 | + private String channelCode; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "支付订单编号 pay_order 表id") | |
| 34 | + private Long orderId; | |
| 35 | + | |
| 36 | + @ApiModelProperty(value = "交易订单号 pay_extension 表no 字段") | |
| 37 | + private String tradeNo; | |
| 38 | + | |
| 39 | + @ApiModelProperty(value = "商户订单编号(商户系统生成)") | |
| 40 | + private String merchantOrderId; | |
| 41 | + | |
| 42 | + @ApiModelProperty(value = "商户退款订单号(商户系统生成)") | |
| 43 | + private String merchantRefundNo; | |
| 44 | + | |
| 45 | + @ApiModelProperty(value = "异步通知商户地址") | |
| 46 | + private String notifyUrl; | |
| 47 | + | |
| 48 | + @ApiModelProperty(value = "通知商户退款结果的回调状态") | |
| 49 | + private Integer notifyStatus; | |
| 50 | + | |
| 51 | + @ApiModelProperty(value = "退款状态") | |
| 52 | + private Integer status; | |
| 53 | + | |
| 54 | + @ApiModelProperty(value = "退款类型(部分退款,全部退款)") | |
| 55 | + private Integer type; | |
| 56 | + | |
| 57 | + @ApiModelProperty(value = "支付金额,单位分") | |
| 58 | + private Long payAmount; | |
| 59 | + | |
| 60 | + @ApiModelProperty(value = "退款金额,单位分") | |
| 61 | + private Long refundAmount; | |
| 62 | + | |
| 63 | + @ApiModelProperty(value = "退款原因") | |
| 64 | + private String reason; | |
| 65 | + | |
| 66 | + @ApiModelProperty(value = "用户 IP") | |
| 67 | + private String userIp; | |
| 68 | + | |
| 69 | + @ApiModelProperty(value = "渠道订单号,pay_order 中的channel_order_no 对应") | |
| 70 | + private String channelOrderNo; | |
| 71 | + | |
| 72 | + @ApiModelProperty(value = "渠道退款单号,渠道返回") | |
| 73 | + private String channelRefundNo; | |
| 74 | + | |
| 75 | + @ApiModelProperty(value = "渠道调用报错时,错误码") | |
| 76 | + private String channelErrorCode; | |
| 77 | + | |
| 78 | + @ApiModelProperty(value = "渠道调用报错时,错误信息") | |
| 79 | + private String channelErrorMsg; | |
| 80 | + | |
| 81 | + @ApiModelProperty(value = "支付渠道的额外参数") | |
| 82 | + private String channelExtras; | |
| 83 | + | |
| 84 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 85 | + @ApiModelProperty(value = "开始退款失效时间") | |
| 86 | + private Date beginExpireTime; | |
| 87 | + | |
| 88 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 89 | + @ApiModelProperty(value = "结束退款失效时间") | |
| 90 | + private Date endExpireTime; | |
| 91 | + | |
| 92 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 93 | + @ApiModelProperty(value = "开始退款成功时间") | |
| 94 | + private Date beginSuccessTime; | |
| 95 | + | |
| 96 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 97 | + @ApiModelProperty(value = "结束退款成功时间") | |
| 98 | + private Date endSuccessTime; | |
| 99 | + | |
| 100 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 101 | + @ApiModelProperty(value = "开始退款通知时间") | |
| 102 | + private Date beginNotifyTime; | |
| 103 | + | |
| 104 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 105 | + @ApiModelProperty(value = "结束退款通知时间") | |
| 106 | + private Date endNotifyTime; | |
| 107 | + | |
| 108 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 109 | + @ApiModelProperty(value = "开始创建时间") | |
| 110 | + private Date beginCreateTime; | |
| 111 | + | |
| 112 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 113 | + @ApiModelProperty(value = "结束创建时间") | |
| 114 | + private Date endCreateTime; | |
| 115 | + | |
| 116 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.util.Date; | |
| 10 | + | |
| 11 | +@ApiModel("退款订单 Response VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class PayRefundRespVO extends PayRefundBaseVO { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "支付退款编号", required = true) | |
| 18 | + private Long id; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 21 | + private Date createTime; | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundUpdateReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import io.swagger.annotations.*; | |
| 5 | +import javax.validation.constraints.*; | |
| 6 | + | |
| 7 | +@ApiModel("退款订单更新 Request VO") | |
| 8 | +@Data | |
| 9 | +@EqualsAndHashCode(callSuper = true) | |
| 10 | +@ToString(callSuper = true) | |
| 11 | +public class PayRefundUpdateReqVO extends PayRefundBaseVO { | |
| 12 | + | |
| 13 | + @ApiModelProperty(value = "支付退款编号", required = true) | |
| 14 | + @NotNull(message = "支付退款编号不能为空") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.convert.app; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserPageItemRespVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 8 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 9 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 10 | + | |
| 11 | +import org.mapstruct.Mapper; | |
| 12 | +import org.mapstruct.factory.Mappers; | |
| 13 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 支付应用信息 Convert | |
| 17 | + * | |
| 18 | + * @author 芋艿 | |
| 19 | + */ | |
| 20 | +@Mapper | |
| 21 | +public interface PayAppConvert { | |
| 22 | + | |
| 23 | + PayAppConvert INSTANCE = Mappers.getMapper(PayAppConvert.class); | |
| 24 | + | |
| 25 | + PayAppPageItemRespVO pageConvert (PayAppDO bean); | |
| 26 | + | |
| 27 | + PayAppPageItemRespVO.PayMerchant convert(PayMerchantDO bean); | |
| 28 | + | |
| 29 | + PayAppDO convert(PayAppCreateReqVO bean); | |
| 30 | + | |
| 31 | + PayAppDO convert(PayAppUpdateReqVO bean); | |
| 32 | + | |
| 33 | + PayAppRespVO convert(PayAppDO bean); | |
| 34 | + | |
| 35 | + List<PayAppRespVO> convertList(List<PayAppDO> list); | |
| 36 | + | |
| 37 | + PageResult<PayAppRespVO> convertPage(PageResult<PayAppDO> page); | |
| 38 | + | |
| 39 | + List<PayAppExcelVO> convertList02(List<PayAppDO> list); | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.convert.channel; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | + | |
| 8 | +import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; | |
| 9 | +import org.mapstruct.Mapper; | |
| 10 | +import org.mapstruct.Mapping; | |
| 11 | +import org.mapstruct.factory.Mappers; | |
| 12 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 支付渠道 | |
| 16 | + Convert | |
| 17 | + * | |
| 18 | + * @author 芋艿 | |
| 19 | + */ | |
| 20 | +@Mapper | |
| 21 | +public interface PayChannelConvert { | |
| 22 | + | |
| 23 | + PayChannelConvert INSTANCE = Mappers.getMapper(PayChannelConvert.class); | |
| 24 | + | |
| 25 | + @Mapping(target = "config",ignore = true) | |
| 26 | + PayChannelDO convert(PayChannelCreateReqVO bean); | |
| 27 | + | |
| 28 | + @Mapping(target = "config",ignore = true) | |
| 29 | + PayChannelDO convert(PayChannelUpdateReqVO bean); | |
| 30 | + | |
| 31 | + @Mapping(target = "config",expression = "java(cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString(bean.getConfig()))") | |
| 32 | + PayChannelRespVO convert(PayChannelDO bean); | |
| 33 | + | |
| 34 | + List<PayChannelRespVO> convertList(List<PayChannelDO> list); | |
| 35 | + | |
| 36 | + PageResult<PayChannelRespVO> convertPage(PageResult<PayChannelDO> page); | |
| 37 | + | |
| 38 | + List<PayChannelExcelVO> convertList02(List<PayChannelDO> list); | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/merchant/PayMerchantConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.convert.merchant; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | + | |
| 8 | +import org.mapstruct.Mapper; | |
| 9 | +import org.mapstruct.factory.Mappers; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 支付商户信息 Convert | |
| 14 | + * | |
| 15 | + * @author 芋艿 | |
| 16 | + */ | |
| 17 | +@Mapper | |
| 18 | +public interface PayMerchantConvert { | |
| 19 | + | |
| 20 | + PayMerchantConvert INSTANCE = Mappers.getMapper(PayMerchantConvert.class); | |
| 21 | + | |
| 22 | + PayMerchantDO convert(PayMerchantCreateReqVO bean); | |
| 23 | + | |
| 24 | + PayMerchantDO convert(PayMerchantUpdateReqVO bean); | |
| 25 | + | |
| 26 | + PayMerchantRespVO convert(PayMerchantDO bean); | |
| 27 | + | |
| 28 | + List<PayMerchantRespVO> convertList(List<PayMerchantDO> list); | |
| 29 | + | |
| 30 | + PageResult<PayMerchantRespVO> convertPage(PageResult<PayMerchantDO> page); | |
| 31 | + | |
| 32 | + List<PayMerchantExcelVO> convertList02(List<PayMerchantDO> list); | |
| 33 | + | |
| 34 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/order/PayOrderConvert.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.convert.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderDetailsRespVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExcelVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageItemRespVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderRespVO; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 8 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; | |
| 9 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 10 | +import org.mapstruct.Mapper; | |
| 11 | +import org.mapstruct.factory.Mappers; | |
| 12 | + | |
| 13 | +import java.math.BigDecimal; | |
| 14 | +import java.math.RoundingMode; | |
| 15 | +import java.util.List; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * 支付订单 Convert | |
| 19 | + * | |
| 20 | + * @author aquan | |
| 21 | + */ | |
| 22 | +@Mapper | |
| 23 | +public interface PayOrderConvert { | |
| 24 | + | |
| 25 | + PayOrderConvert INSTANCE = Mappers.getMapper(PayOrderConvert.class); | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + PayOrderRespVO convert(PayOrderDO bean); | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 订单DO 转换为 详细订单 RespVO | |
| 33 | + * | |
| 34 | + * @param bean 订单DO | |
| 35 | + * @return 详细订单 RespVO | |
| 36 | + */ | |
| 37 | + PayOrderDetailsRespVO orderDetailConvert(PayOrderDO bean); | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 订单扩展DO 转换为 详细订单扩展 RespVO | |
| 41 | + * | |
| 42 | + * @param bean 订单扩展DO | |
| 43 | + * @return 详细订单扩展 RespVO | |
| 44 | + */ | |
| 45 | + PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean); | |
| 46 | + | |
| 47 | + List<PayOrderRespVO> convertList(List<PayOrderDO> list); | |
| 48 | + | |
| 49 | + PageResult<PayOrderRespVO> convertPage(PageResult<PayOrderDO> page); | |
| 50 | + | |
| 51 | + List<PayOrderExcelVO> convertList02(List<PayOrderDO> list); | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 订单DO转自定义分页对象 | |
| 55 | + * | |
| 56 | + * @param bean 订单DO | |
| 57 | + * @return 分页对象 | |
| 58 | + */ | |
| 59 | + PayOrderPageItemRespVO pageConvertItemPage(PayOrderDO bean); | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * 订单DO 转 订单导出excel VO | |
| 63 | + * | |
| 64 | + * @param bean 订单 DO | |
| 65 | + * @return 订单导出excel VO | |
| 66 | + */ | |
| 67 | + default PayOrderExcelVO excelConvert(PayOrderDO bean) { | |
| 68 | + if (bean == null) { | |
| 69 | + return null; | |
| 70 | + } | |
| 71 | + | |
| 72 | + PayOrderExcelVO payOrderExcelVO = new PayOrderExcelVO(); | |
| 73 | + | |
| 74 | + payOrderExcelVO.setId(bean.getId()); | |
| 75 | + payOrderExcelVO.setSubject(bean.getSubject()); | |
| 76 | + payOrderExcelVO.setMerchantOrderId(bean.getMerchantOrderId()); | |
| 77 | + payOrderExcelVO.setChannelOrderNo(bean.getChannelOrderNo()); | |
| 78 | + payOrderExcelVO.setStatus(bean.getStatus()); | |
| 79 | + payOrderExcelVO.setNotifyStatus(bean.getNotifyStatus()); | |
| 80 | + payOrderExcelVO.setNotifyUrl(bean.getNotifyUrl()); | |
| 81 | + payOrderExcelVO.setCreateTime(bean.getCreateTime()); | |
| 82 | + payOrderExcelVO.setSuccessTime(bean.getSuccessTime()); | |
| 83 | + payOrderExcelVO.setExpireTime(bean.getExpireTime()); | |
| 84 | + payOrderExcelVO.setNotifyTime(bean.getNotifyTime()); | |
| 85 | + payOrderExcelVO.setUserIp(bean.getUserIp()); | |
| 86 | + payOrderExcelVO.setRefundStatus(bean.getRefundStatus()); | |
| 87 | + payOrderExcelVO.setRefundTimes(bean.getRefundTimes()); | |
| 88 | + payOrderExcelVO.setBody(bean.getBody()); | |
| 89 | + | |
| 90 | + BigDecimal multiple = new BigDecimal(100); | |
| 91 | + | |
| 92 | + payOrderExcelVO.setAmount(BigDecimal.valueOf(bean.getAmount()) | |
| 93 | + .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | |
| 94 | + | |
| 95 | + payOrderExcelVO.setChannelFeeAmount(BigDecimal.valueOf(bean.getChannelFeeAmount()) | |
| 96 | + .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | |
| 97 | + payOrderExcelVO.setChannelFeeRate(java.math.BigDecimal.valueOf(bean.getChannelFeeRate()) | |
| 98 | + .multiply(multiple).toString()); | |
| 99 | + payOrderExcelVO.setRefundAmount(BigDecimal.valueOf(bean.getRefundAmount()) | |
| 100 | + .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | |
| 101 | + | |
| 102 | + return payOrderExcelVO; | |
| 103 | + } | |
| 104 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/refund/PayRefundConvert.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.convert.refund; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.*; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import org.mapstruct.Mapper; | |
| 7 | +import org.mapstruct.factory.Mappers; | |
| 8 | + | |
| 9 | +import java.math.BigDecimal; | |
| 10 | +import java.math.RoundingMode; | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 退款订单 Convert | |
| 15 | + * | |
| 16 | + * @author aquan | |
| 17 | + */ | |
| 18 | +@Mapper | |
| 19 | +public interface PayRefundConvert { | |
| 20 | + | |
| 21 | + PayRefundConvert INSTANCE = Mappers.getMapper(PayRefundConvert.class); | |
| 22 | + | |
| 23 | + PayRefundDO convert(PayRefundCreateReqVO bean); | |
| 24 | + | |
| 25 | + PayRefundDO convert(PayRefundUpdateReqVO bean); | |
| 26 | + | |
| 27 | + PayRefundRespVO convert(PayRefundDO bean); | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 退款订单 DO 转 退款详情订单 VO | |
| 31 | + * | |
| 32 | + * @param bean 退款订单 DO | |
| 33 | + * @return 退款详情订单 VO | |
| 34 | + */ | |
| 35 | + PayRefundDetailsRespVO refundDetailConvert(PayRefundDO bean); | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * 退款订单DO 转 分页退款条目VO | |
| 39 | + * | |
| 40 | + * @param bean 退款订单DO | |
| 41 | + * @return 分页退款条目VO | |
| 42 | + */ | |
| 43 | + PayRefundPageItemRespVO pageItemConvert(PayRefundDO bean); | |
| 44 | + | |
| 45 | + List<PayRefundRespVO> convertList(List<PayRefundDO> list); | |
| 46 | + | |
| 47 | + PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page); | |
| 48 | + | |
| 49 | + List<PayRefundExcelVO> convertList02(List<PayRefundDO> list); | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * 退款订单DO 转 导出excel VO | |
| 53 | + * | |
| 54 | + * @param bean 退款订单DO | |
| 55 | + * @return 导出 excel VO | |
| 56 | + */ | |
| 57 | + default PayRefundExcelVO excelConvert(PayRefundDO bean) { | |
| 58 | + if (bean == null) { | |
| 59 | + return null; | |
| 60 | + } | |
| 61 | + | |
| 62 | + PayRefundExcelVO payRefundExcelVO = new PayRefundExcelVO(); | |
| 63 | + | |
| 64 | + payRefundExcelVO.setId(bean.getId()); | |
| 65 | + payRefundExcelVO.setTradeNo(bean.getTradeNo()); | |
| 66 | + payRefundExcelVO.setMerchantOrderId(bean.getMerchantOrderId()); | |
| 67 | + payRefundExcelVO.setMerchantRefundNo(bean.getMerchantRefundNo()); | |
| 68 | + payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl()); | |
| 69 | + payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus()); | |
| 70 | + payRefundExcelVO.setStatus(bean.getStatus()); | |
| 71 | + payRefundExcelVO.setType(bean.getType()); | |
| 72 | + payRefundExcelVO.setReason(bean.getReason()); | |
| 73 | + payRefundExcelVO.setUserIp(bean.getUserIp()); | |
| 74 | + payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo()); | |
| 75 | + payRefundExcelVO.setChannelRefundNo(bean.getChannelRefundNo()); | |
| 76 | + payRefundExcelVO.setExpireTime(bean.getExpireTime()); | |
| 77 | + payRefundExcelVO.setSuccessTime(bean.getSuccessTime()); | |
| 78 | + payRefundExcelVO.setNotifyTime(bean.getNotifyTime()); | |
| 79 | + payRefundExcelVO.setCreateTime(bean.getCreateTime()); | |
| 80 | + | |
| 81 | + BigDecimal multiple = new BigDecimal(100); | |
| 82 | + payRefundExcelVO.setPayAmount(BigDecimal.valueOf(bean.getPayAmount()) | |
| 83 | + .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | |
| 84 | + payRefundExcelVO.setRefundAmount(BigDecimal.valueOf(bean.getRefundAmount()) | |
| 85 | + .divide(multiple, 2, RoundingMode.HALF_UP).toString()); | |
| 86 | + | |
| 87 | + return payRefundExcelVO; | |
| 88 | + } | |
| 89 | + | |
| 90 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | |
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 10 | +import org.apache.ibatis.annotations.Mapper; | |
| 11 | + | |
| 12 | +import java.util.Collection; | |
| 13 | +import java.util.List; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 支付应用信息 Mapper | |
| 17 | + * | |
| 18 | + * @author aquan | |
| 19 | + */ | |
| 20 | +@Mapper | |
| 21 | +public interface PayAppMapper extends BaseMapperX<PayAppDO> { | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 分页查询 | |
| 25 | + * | |
| 26 | + * @param reqVO 支付应用信息分页查询条件 | |
| 27 | + * @param merchantIds 商户 ID 集合 | |
| 28 | + * @return 支付应用信息 | |
| 29 | + */ | |
| 30 | + default PageResult<PayAppDO> selectPage(PayAppPageReqVO reqVO, Collection<Long> merchantIds) { | |
| 31 | + return selectPage(reqVO, new QueryWrapperX<PayAppDO>() | |
| 32 | + .likeIfPresent("name", reqVO.getName()) | |
| 33 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 34 | + .eqIfPresent("remark", reqVO.getRemark()) | |
| 35 | + .eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl()) | |
| 36 | + .eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl()) | |
| 37 | + .inIfPresent("merchant_id", merchantIds) | |
| 38 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 39 | + .orderByDesc("id")); | |
| 40 | + } | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * 列表查询 | |
| 44 | + * | |
| 45 | + * @param reqVO 支付应用信息 Excel 导出查询条件 | |
| 46 | + * @param merchantIds 商户 ID 集合 | |
| 47 | + * @return 支付应用信息 | |
| 48 | + */ | |
| 49 | + default List<PayAppDO> selectList(PayAppExportReqVO reqVO, Collection<Long> merchantIds) { | |
| 50 | + return selectList(new QueryWrapperX<PayAppDO>() | |
| 51 | + .likeIfPresent("name", reqVO.getName()) | |
| 52 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 53 | + .eqIfPresent("remark", reqVO.getRemark()) | |
| 54 | + .eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl()) | |
| 55 | + .eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl()) | |
| 56 | + .inIfPresent("merchant_id", merchantIds) | |
| 57 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 58 | + .orderByDesc("id")); | |
| 59 | + } | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * 根据 商户 ID 查询支付应用信息 | |
| 63 | + * | |
| 64 | + * @param merchantId 商户 ID | |
| 65 | + * @return 支付应用信息列表 | |
| 66 | + */ | |
| 67 | + default List<PayAppDO> getListByMerchantId(String merchantId) { | |
| 68 | + return selectList(new LambdaQueryWrapper<PayAppDO>() | |
| 69 | + .select(PayAppDO::getId, PayAppDO::getName) | |
| 70 | + .eq(PayAppDO::getMerchantId, merchantId)); | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 根据商户号统计存在的支付应用数量 | |
| 75 | + * | |
| 76 | + * @param merchantId 商户 ID | |
| 77 | + * @return 支付应用数量 | |
| 78 | + */ | |
| 79 | + default Long selectCount(Long merchantId) { | |
| 80 | + return selectCount(new LambdaQueryWrapper<PayAppDO>().eq(PayAppDO::getMerchantId, merchantId)); | |
| 81 | + } | |
| 82 | + | |
| 83 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | |
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
| 10 | +import org.apache.ibatis.annotations.Mapper; | |
| 11 | + | |
| 12 | +import java.util.Collection; | |
| 13 | +import java.util.List; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 支付渠道 | |
| 17 | + Mapper | |
| 18 | + * | |
| 19 | + * @author 芋艿 | |
| 20 | + */ | |
| 21 | +@Mapper | |
| 22 | +public interface PayChannelMapper extends BaseMapperX<PayChannelDO> { | |
| 23 | + | |
| 24 | + default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) { | |
| 25 | + return selectPage(reqVO, new QueryWrapperX<PayChannelDO>() | |
| 26 | + .eqIfPresent("code", reqVO.getCode()) | |
| 27 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 28 | + .eqIfPresent("remark", reqVO.getRemark()) | |
| 29 | + .eqIfPresent("fee_rate", reqVO.getFeeRate()) | |
| 30 | + .eqIfPresent("merchant_id", reqVO.getMerchantId()) | |
| 31 | + .eqIfPresent("app_id", reqVO.getAppId()) | |
| 32 | + // .eqIfPresent("config", reqVO.getConfig()) | |
| 33 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 34 | + .orderByDesc("id") ); | |
| 35 | + } | |
| 36 | + | |
| 37 | + default List<PayChannelDO> selectList(PayChannelExportReqVO reqVO) { | |
| 38 | + return selectList(new QueryWrapperX<PayChannelDO>() | |
| 39 | + .eqIfPresent("code", reqVO.getCode()) | |
| 40 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 41 | + .eqIfPresent("remark", reqVO.getRemark()) | |
| 42 | + .eqIfPresent("fee_rate", reqVO.getFeeRate()) | |
| 43 | + .eqIfPresent("merchant_id", reqVO.getMerchantId()) | |
| 44 | + .eqIfPresent("app_id", reqVO.getAppId()) | |
| 45 | + // .eqIfPresent("config", reqVO.getConfig()) | |
| 46 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 47 | + .orderByDesc("id") ); | |
| 48 | + } | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 根据条件获取通道数量 | |
| 52 | + * | |
| 53 | + * @param merchantId 商户编号 | |
| 54 | + * @param appid 应用编号 | |
| 55 | + * @param code 通道编码 | |
| 56 | + * @return 数量 | |
| 57 | + */ | |
| 58 | + default Integer selectCount(Long merchantId, Long appid, String code) { | |
| 59 | + return this.selectCount(new QueryWrapper<PayChannelDO>().lambda() | |
| 60 | + .eq(PayChannelDO::getMerchantId, merchantId) | |
| 61 | + .eq(PayChannelDO::getAppId, appid) | |
| 62 | + .eq(PayChannelDO::getCode, code)).intValue(); | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 根据条件获取通道 | |
| 67 | + * | |
| 68 | + * @param merchantId 商户编号 | |
| 69 | + * @param appid 应用编号 | |
| 70 | + * @param code 通道编码 | |
| 71 | + * @return 数量 | |
| 72 | + */ | |
| 73 | + default PayChannelDO selectOne(Long merchantId, Long appid, String code) { | |
| 74 | + return this.selectOne((new QueryWrapper<PayChannelDO>().lambda() | |
| 75 | + .eq(PayChannelDO::getMerchantId, merchantId) | |
| 76 | + .eq(PayChannelDO::getAppId, appid) | |
| 77 | + .eq(PayChannelDO::getCode, code) | |
| 78 | + )); | |
| 79 | + } | |
| 80 | + | |
| 81 | + /** | |
| 82 | + * 根据支付应用ID集合获得支付渠道列表 | |
| 83 | + * | |
| 84 | + * @param appIds 应用编号集合 | |
| 85 | + * @return 支付渠道列表 | |
| 86 | + */ | |
| 87 | + default List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds){ | |
| 88 | + return this.selectList(new QueryWrapper<PayChannelDO>().lambda() | |
| 89 | + .in(PayChannelDO::getAppId, appIds)); | |
| 90 | + } | |
| 91 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/merchant/PayMerchantMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 支付商户信息 Mapper | |
| 15 | + * | |
| 16 | + * @author 芋艿 | |
| 17 | + */ | |
| 18 | +@Mapper | |
| 19 | +public interface PayMerchantMapper extends BaseMapperX<PayMerchantDO> { | |
| 20 | + | |
| 21 | + default PageResult<PayMerchantDO> selectPage(PayMerchantPageReqVO reqVO) { | |
| 22 | + return selectPage(reqVO, new QueryWrapperX<PayMerchantDO>() | |
| 23 | + .likeIfPresent("no", reqVO.getNo()) | |
| 24 | + .likeIfPresent("name", reqVO.getName()) | |
| 25 | + .likeIfPresent("short_name", reqVO.getShortName()) | |
| 26 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 27 | + .eqIfPresent("remark", reqVO.getRemark()) | |
| 28 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 29 | + .orderByDesc("id")); | |
| 30 | + } | |
| 31 | + | |
| 32 | + default List<PayMerchantDO> selectList(PayMerchantExportReqVO reqVO) { | |
| 33 | + return selectList(new QueryWrapperX<PayMerchantDO>() | |
| 34 | + .likeIfPresent("no", reqVO.getNo()) | |
| 35 | + .likeIfPresent("name", reqVO.getName()) | |
| 36 | + .likeIfPresent("short_name", reqVO.getShortName()) | |
| 37 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 38 | + .eqIfPresent("remark", reqVO.getRemark()) | |
| 39 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 40 | + .orderByDesc("id")); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 根据商户名称模糊查询商户集合 | |
| 45 | + * | |
| 46 | + * @param merchantName 商户名称 | |
| 47 | + * @return 商户集合 | |
| 48 | + */ | |
| 49 | + default List<PayMerchantDO> getMerchantListByName(String merchantName) { | |
| 50 | + return this.selectList(new QueryWrapperX<PayMerchantDO>() | |
| 51 | + .likeIfPresent("name", merchantName)); | |
| 52 | + } | |
| 53 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderExtensionMapper.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import org.apache.ibatis.annotations.Mapper; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 支付订单 Mapper | |
| 9 | + * | |
| 10 | + * @author aquan | |
| 11 | + */ | |
| 12 | +@Mapper | |
| 13 | +public interface PayOrderExtensionMapper extends BaseMapperX<PayOrderExtensionDO> { | |
| 14 | + | |
| 15 | + | |
| 16 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderMapper.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | |
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 10 | +import org.apache.ibatis.annotations.Mapper; | |
| 11 | + | |
| 12 | +import java.util.Collection; | |
| 13 | +import java.util.List; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 支付订单 Mapper 组件 | |
| 17 | + * | |
| 18 | + * @author aquan | |
| 19 | + */ | |
| 20 | +@Mapper | |
| 21 | +public interface PayOrderMapper extends BaseMapperX<PayOrderDO> { | |
| 22 | + | |
| 23 | + default PageResult<PayOrderDO> selectPage(PayOrderPageReqVO reqVO) { | |
| 24 | + return selectPage(reqVO, new QueryWrapperX<PayOrderDO>() | |
| 25 | + .eqIfPresent("merchant_id", reqVO.getMerchantId()) | |
| 26 | + .eqIfPresent("app_id", reqVO.getAppId()) | |
| 27 | + .eqIfPresent("channel_id", reqVO.getChannelId()) | |
| 28 | + .eqIfPresent("channel_code", reqVO.getChannelCode()) | |
| 29 | + .likeIfPresent("merchant_order_id", reqVO.getMerchantOrderId()) | |
| 30 | + .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | |
| 31 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 32 | + .eqIfPresent("refund_status", reqVO.getRefundStatus()) | |
| 33 | + .likeIfPresent("channel_order_no", reqVO.getChannelOrderNo()) | |
| 34 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 35 | + .orderByDesc("id")); | |
| 36 | + } | |
| 37 | + | |
| 38 | + default List<PayOrderDO> selectList(PayOrderExportReqVO reqVO) { | |
| 39 | + return selectList(new QueryWrapperX<PayOrderDO>() | |
| 40 | + .eqIfPresent("merchant_id", reqVO.getMerchantId()) | |
| 41 | + .eqIfPresent("app_id", reqVO.getAppId()) | |
| 42 | + .eqIfPresent("channel_id", reqVO.getChannelId()) | |
| 43 | + .eqIfPresent("channel_code", reqVO.getChannelCode()) | |
| 44 | + .likeIfPresent("merchant_order_id", reqVO.getMerchantOrderId()) | |
| 45 | + .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | |
| 46 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 47 | + .eqIfPresent("refund_status", reqVO.getRefundStatus()) | |
| 48 | + .likeIfPresent("channel_order_no", reqVO.getChannelOrderNo()) | |
| 49 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 50 | + .orderByDesc("id")); | |
| 51 | + } | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 根据订单 ID 集合查询订单商品名称 | |
| 55 | + * | |
| 56 | + * @param idList 订单 ID 集合 | |
| 57 | + * @return 只包含商品名称和标题的订单集合对象 | |
| 58 | + */ | |
| 59 | + default List<PayOrderDO> findByIdListQueryOrderSubject(Collection<Long> idList) { | |
| 60 | + return selectList(new LambdaQueryWrapper<PayOrderDO>() | |
| 61 | + .select(PayOrderDO::getId, PayOrderDO::getSubject) | |
| 62 | + .in(PayOrderDO::getId, idList)); | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 查询符合的订单数量 | |
| 67 | + * | |
| 68 | + * @param appId 应用编号 | |
| 69 | + * @param status 订单状态 | |
| 70 | + * @return 条数 | |
| 71 | + */ | |
| 72 | + default Long selectCount(Long appId, Integer status) { | |
| 73 | + | |
| 74 | + return selectCount(new LambdaQueryWrapper<PayOrderDO>() | |
| 75 | + .eq(PayOrderDO::getAppId, appId) | |
| 76 | + .in(PayOrderDO::getStatus, status)); | |
| 77 | + } | |
| 78 | + | |
| 79 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayRefundMapper.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | |
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 10 | +import org.apache.ibatis.annotations.Mapper; | |
| 11 | + | |
| 12 | +import java.util.List; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 退款订单 Mapper | |
| 16 | + * | |
| 17 | + * @author aquan | |
| 18 | + */ | |
| 19 | +@Mapper | |
| 20 | +public interface PayRefundMapper extends BaseMapperX<PayRefundDO> { | |
| 21 | + | |
| 22 | + default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) { | |
| 23 | + return selectPage(reqVO, new QueryWrapperX<PayRefundDO>() | |
| 24 | + .eqIfPresent("merchant_id", reqVO.getMerchantId()) | |
| 25 | + .eqIfPresent("app_id", reqVO.getAppId()) | |
| 26 | + .eqIfPresent("channel_code", reqVO.getChannelCode()) | |
| 27 | + .likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo()) | |
| 28 | + .eqIfPresent("type", reqVO.getType()) | |
| 29 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 30 | + .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | |
| 31 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 32 | + .orderByDesc("id")); | |
| 33 | + } | |
| 34 | + | |
| 35 | + default List<PayRefundDO> selectList(PayRefundExportReqVO reqVO) { | |
| 36 | + return selectList(new QueryWrapperX<PayRefundDO>() | |
| 37 | + .eqIfPresent("merchant_id", reqVO.getMerchantId()) | |
| 38 | + .eqIfPresent("app_id", reqVO.getAppId()) | |
| 39 | + .eqIfPresent("channel_code", reqVO.getChannelCode()) | |
| 40 | + .likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo()) | |
| 41 | + .eqIfPresent("type", reqVO.getType()) | |
| 42 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 43 | + .eqIfPresent("notify_status", reqVO.getNotifyStatus()) | |
| 44 | + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) | |
| 45 | + .orderByDesc("id")); | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 查询符合的订单数量 | |
| 50 | + * | |
| 51 | + * @param appId 应用编号 | |
| 52 | + * @param status 订单状态 | |
| 53 | + * @return 条数 | |
| 54 | + */ | |
| 55 | + default Long selectCount(Long appId, Integer status) { | |
| 56 | + | |
| 57 | + return selectCount(new LambdaQueryWrapper<PayRefundDO>() | |
| 58 | + .eq(PayRefundDO::getAppId, appId) | |
| 59 | + .eq(PayRefundDO::getStatus, status)); | |
| 60 | + } | |
| 61 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/enums/PayErrorCodeConstants.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.enums; | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.app; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 10 | + | |
| 11 | +import javax.validation.Valid; | |
| 12 | +import java.util.Collection; | |
| 13 | +import java.util.List; | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * 支付应用信息 Service 接口 | |
| 18 | + * | |
| 19 | + * @author 芋艿 | |
| 20 | + */ | |
| 21 | +public interface PayAppService { | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 创建支付应用信息 | |
| 25 | + * | |
| 26 | + * @param createReqVO 创建信息 | |
| 27 | + * @return 编号 | |
| 28 | + */ | |
| 29 | + Long createApp(@Valid PayAppCreateReqVO createReqVO); | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 更新支付应用信息 | |
| 33 | + * | |
| 34 | + * @param updateReqVO 更新信息 | |
| 35 | + */ | |
| 36 | + void updateApp(@Valid PayAppUpdateReqVO updateReqVO); | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 删除支付应用信息 | |
| 40 | + * | |
| 41 | + * @param id 编号 | |
| 42 | + */ | |
| 43 | + void deleteApp(Long id); | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 获得支付应用信息 | |
| 47 | + * | |
| 48 | + * @param id 编号 | |
| 49 | + * @return 支付应用信息 | |
| 50 | + */ | |
| 51 | + PayAppDO getApp(Long id); | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 获得支付应用信息列表 | |
| 55 | + * | |
| 56 | + * @param ids 编号 | |
| 57 | + * @return 支付应用信息列表 | |
| 58 | + */ | |
| 59 | + List<PayAppDO> getAppList(Collection<Long> ids); | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * 获得支付应用信息分页 | |
| 63 | + * | |
| 64 | + * @param pageReqVO 分页查询 | |
| 65 | + * @return 支付应用信息分页 | |
| 66 | + */ | |
| 67 | + PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO); | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * 获得支付应用信息列表, 用于 Excel 导出 | |
| 71 | + * | |
| 72 | + * @param exportReqVO 查询条件 | |
| 73 | + * @return 支付应用信息列表 | |
| 74 | + */ | |
| 75 | + List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO); | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * 修改应用信息状态 | |
| 79 | + * | |
| 80 | + * @param id 应用编号 | |
| 81 | + * @param status 状态{@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} | |
| 82 | + */ | |
| 83 | + void updateAppStatus(Long id, Integer status); | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 根据商户 ID 获得支付应用信息列表, | |
| 87 | + * | |
| 88 | + * @param merchantId 商户 ID | |
| 89 | + * @return 支付应用信息列表 | |
| 90 | + */ | |
| 91 | + List<PayAppDO> getListByMerchantId(String merchantId); | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * 获得指定编号的商户 Map | |
| 95 | + * | |
| 96 | + * @param appIdList 应用编号集合 | |
| 97 | + * @return 商户 Map | |
| 98 | + */ | |
| 99 | + default Map<Long, PayAppDO> getAppMap(Collection<Long> appIdList) { | |
| 100 | + List<PayAppDO> list = this.getAppList(appIdList); | |
| 101 | + return CollectionUtils.convertMap(list, PayAppDO::getId); | |
| 102 | + } | |
| 103 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.app.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollectionUtil; | |
| 4 | +import cn.hutool.core.util.StrUtil; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; | |
| 11 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; | |
| 12 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper; | |
| 13 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper; | |
| 14 | +import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; | |
| 15 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 16 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 17 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; | |
| 18 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; | |
| 19 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 20 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 21 | +import com.google.common.annotations.VisibleForTesting; | |
| 22 | +import org.springframework.stereotype.Service; | |
| 23 | +import org.springframework.validation.annotation.Validated; | |
| 24 | + | |
| 25 | +import javax.annotation.Resource; | |
| 26 | +import java.util.*; | |
| 27 | + | |
| 28 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; | |
| 29 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 30 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * 支付应用信息 Service 实现类 | |
| 34 | + * | |
| 35 | + * @author aquan | |
| 36 | + */ | |
| 37 | +@Service | |
| 38 | +@Validated | |
| 39 | +public class PayAppServiceImpl implements PayAppService { | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private PayAppMapper appMapper; | |
| 43 | + | |
| 44 | + @Resource | |
| 45 | + private PayMerchantMapper merchantMapper; | |
| 46 | + | |
| 47 | + @Resource | |
| 48 | + private PayOrderMapper orderMapper; | |
| 49 | + | |
| 50 | + @Resource | |
| 51 | + private PayRefundMapper refundMapper; | |
| 52 | + | |
| 53 | + | |
| 54 | + @Override | |
| 55 | + public Long createApp(PayAppCreateReqVO createReqVO) { | |
| 56 | + // 插入 | |
| 57 | + PayAppDO app = PayAppConvert.INSTANCE.convert(createReqVO); | |
| 58 | + appMapper.insert(app); | |
| 59 | + // 返回 | |
| 60 | + return app.getId(); | |
| 61 | + } | |
| 62 | + | |
| 63 | + @Override | |
| 64 | + public void updateApp(PayAppUpdateReqVO updateReqVO) { | |
| 65 | + // 校验存在 | |
| 66 | + this.validateAppExists(updateReqVO.getId()); | |
| 67 | + // 更新 | |
| 68 | + PayAppDO updateObj = PayAppConvert.INSTANCE.convert(updateReqVO); | |
| 69 | + appMapper.updateById(updateObj); | |
| 70 | + } | |
| 71 | + | |
| 72 | + @Override | |
| 73 | + public void deleteApp(Long id) { | |
| 74 | + // 校验存在 | |
| 75 | + this.validateAppExists(id); | |
| 76 | + this.validateOrderTransactionExist(id); | |
| 77 | + | |
| 78 | + // 删除 | |
| 79 | + appMapper.deleteById(id); | |
| 80 | + } | |
| 81 | + | |
| 82 | + private void validateAppExists(Long id) { | |
| 83 | + if (appMapper.selectById(id) == null) { | |
| 84 | + throw exception(PAY_APP_NOT_FOUND); | |
| 85 | + } | |
| 86 | + } | |
| 87 | + | |
| 88 | + @Override | |
| 89 | + public PayAppDO getApp(Long id) { | |
| 90 | + return appMapper.selectById(id); | |
| 91 | + } | |
| 92 | + | |
| 93 | + @Override | |
| 94 | + public List<PayAppDO> getAppList(Collection<Long> ids) { | |
| 95 | + return appMapper.selectBatchIds(ids); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Override | |
| 99 | + public PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO) { | |
| 100 | + Set<Long> merchantIdList = this.getMerchantCondition(pageReqVO.getMerchantName()); | |
| 101 | + if (StrUtil.isNotBlank(pageReqVO.getMerchantName()) && CollectionUtil.isEmpty(merchantIdList)) { | |
| 102 | + return new PageResult<>(); | |
| 103 | + } | |
| 104 | + return appMapper.selectPage(pageReqVO, merchantIdList); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Override | |
| 108 | + public List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO) { | |
| 109 | + Set<Long> merchantIdList = this.getMerchantCondition(exportReqVO.getMerchantName()); | |
| 110 | + if (StrUtil.isNotBlank(exportReqVO.getMerchantName()) && CollectionUtil.isEmpty(merchantIdList)) { | |
| 111 | + return new ArrayList<>(); | |
| 112 | + } | |
| 113 | + return appMapper.selectList(exportReqVO, merchantIdList); | |
| 114 | + } | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * 获取商户编号集合,根据商户名称模糊查询得到所有的商户编号集合 | |
| 118 | + * | |
| 119 | + * @param merchantName 商户名称 | |
| 120 | + * @return 商户编号集合 | |
| 121 | + */ | |
| 122 | + private Set<Long> getMerchantCondition(String merchantName) { | |
| 123 | + if (StrUtil.isBlank(merchantName)) { | |
| 124 | + return Collections.emptySet(); | |
| 125 | + } | |
| 126 | + return convertSet(merchantMapper.getMerchantListByName(merchantName), PayMerchantDO::getId); | |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * 修改应用信息状态 | |
| 131 | + * | |
| 132 | + * @param id 应用编号 | |
| 133 | + * @param status 状态{@link CommonStatusEnum} | |
| 134 | + */ | |
| 135 | + @Override | |
| 136 | + public void updateAppStatus(Long id, Integer status) { | |
| 137 | + // 校验商户存在 | |
| 138 | + this.checkAppExists(id); | |
| 139 | + // 更新状态 | |
| 140 | + PayAppDO app = new PayAppDO(); | |
| 141 | + app.setId(id); | |
| 142 | + app.setStatus(status); | |
| 143 | + appMapper.updateById(app); | |
| 144 | + } | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * 根据商户 ID 获得支付应用信息列表, | |
| 148 | + * | |
| 149 | + * @param merchantId 商户 ID | |
| 150 | + * @return 支付应用信息列表 | |
| 151 | + */ | |
| 152 | + @Override | |
| 153 | + public List<PayAppDO> getListByMerchantId(String merchantId) { | |
| 154 | + return appMapper.getListByMerchantId(merchantId); | |
| 155 | + } | |
| 156 | + | |
| 157 | + /** | |
| 158 | + * 检查商户是否存在 | |
| 159 | + * | |
| 160 | + * @param id 商户编号 | |
| 161 | + */ | |
| 162 | + @VisibleForTesting | |
| 163 | + public void checkAppExists(Long id) { | |
| 164 | + if (id == null) { | |
| 165 | + return; | |
| 166 | + } | |
| 167 | + PayAppDO payApp = appMapper.selectById(id); | |
| 168 | + if (payApp == null) { | |
| 169 | + throw exception(PAY_APP_NOT_FOUND); | |
| 170 | + } | |
| 171 | + } | |
| 172 | + | |
| 173 | + /** | |
| 174 | + * 验证是否存在交易中或者退款中等处理中状态的订单 | |
| 175 | + * | |
| 176 | + * @param appId 应用 ID | |
| 177 | + */ | |
| 178 | + private void validateOrderTransactionExist(Long appId) { | |
| 179 | + // 查看交易订单 | |
| 180 | + if (orderMapper.selectCount(appId, PayOrderStatusEnum.WAITING.getStatus()) > 0) { | |
| 181 | + throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE); | |
| 182 | + } | |
| 183 | + // 查看退款订单 | |
| 184 | + if (refundMapper.selectCount(appId, PayRefundStatusEnum.CREATE.getStatus()) > 0) { | |
| 185 | + throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE); | |
| 186 | + } | |
| 187 | + } | |
| 188 | + | |
| 189 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.channel; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import org.springframework.web.multipart.MultipartFile; | |
| 7 | + | |
| 8 | +import javax.validation.Valid; | |
| 9 | +import java.util.Collection; | |
| 10 | +import java.util.List; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 支付渠道 Service 接口 | |
| 14 | + * | |
| 15 | + * @author aquan | |
| 16 | + */ | |
| 17 | +public interface PayChannelService { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 创建支付渠道 | |
| 21 | + * | |
| 22 | + * @param createReqVO 创建信息 | |
| 23 | + * @return 编号 | |
| 24 | + */ | |
| 25 | + Long createChannel(@Valid PayChannelCreateReqVO createReqVO); | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 更新支付渠道 | |
| 29 | + * | |
| 30 | + * @param updateReqVO 更新信息 | |
| 31 | + */ | |
| 32 | + void updateChannel(@Valid PayChannelUpdateReqVO updateReqVO); | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 删除支付渠道 | |
| 36 | + * | |
| 37 | + * @param id 编号 | |
| 38 | + */ | |
| 39 | + void deleteChannel(Long id); | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * 获得支付渠道 | |
| 43 | + * | |
| 44 | + * @param id 编号 | |
| 45 | + * @return 支付渠道 | |
| 46 | + */ | |
| 47 | + PayChannelDO getChannel(Long id); | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * 获得支付渠道 | |
| 51 | + * 列表 | |
| 52 | + * | |
| 53 | + * @param ids 编号 | |
| 54 | + * @return 支付渠道 | |
| 55 | + * 列表 | |
| 56 | + */ | |
| 57 | + List<PayChannelDO> getChannelList(Collection<Long> ids); | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * 获得支付渠道 | |
| 61 | + * 分页 | |
| 62 | + * | |
| 63 | + * @param pageReqVO 分页查询 | |
| 64 | + * @return 支付渠道 | |
| 65 | + * 分页 | |
| 66 | + */ | |
| 67 | + PageResult<PayChannelDO> getChannelPage(PayChannelPageReqVO pageReqVO); | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * 获得支付渠道 | |
| 71 | + * 列表, 用于 Excel 导出 | |
| 72 | + * | |
| 73 | + * @param exportReqVO 查询条件 | |
| 74 | + * @return 支付渠道列表 | |
| 75 | + */ | |
| 76 | + List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO); | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 根据支付应用ID集合获得支付渠道列表 | |
| 80 | + * | |
| 81 | + * @param appIds 应用编号集合 | |
| 82 | + * @return 支付渠道列表 | |
| 83 | + */ | |
| 84 | + List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds); | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * 根据条件获取通道数量 | |
| 88 | + * | |
| 89 | + * @param merchantId 商户编号 | |
| 90 | + * @param appid 应用编号 | |
| 91 | + * @param code 通道编码 | |
| 92 | + * @return 数量 | |
| 93 | + */ | |
| 94 | + Integer getChannelCountByConditions(Long merchantId, Long appid, String code); | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * 根据条件获取通道 | |
| 98 | + * | |
| 99 | + * @param merchantId 商户编号 | |
| 100 | + * @param appid 应用编号 | |
| 101 | + * @param code 通道编码 | |
| 102 | + * @return 数量 | |
| 103 | + */ | |
| 104 | + PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code); | |
| 105 | + | |
| 106 | + | |
| 107 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjectUtil; | |
| 4 | +import cn.hutool.json.JSONUtil; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper; | |
| 11 | +import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; | |
| 12 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; | |
| 15 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 16 | +import lombok.extern.slf4j.Slf4j; | |
| 17 | +import org.springframework.stereotype.Service; | |
| 18 | +import org.springframework.validation.annotation.Validated; | |
| 19 | + | |
| 20 | +import javax.annotation.Resource; | |
| 21 | +import javax.validation.Validator; | |
| 22 | +import java.util.Collection; | |
| 23 | +import java.util.List; | |
| 24 | + | |
| 25 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR; | |
| 26 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS; | |
| 27 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * 支付渠道 Service 实现类 | |
| 31 | + * | |
| 32 | + * @author aquan | |
| 33 | + */ | |
| 34 | +@Service | |
| 35 | +@Slf4j | |
| 36 | +@Validated | |
| 37 | +public class PayChannelServiceImpl implements PayChannelService { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private PayChannelMapper channelMapper; | |
| 41 | + | |
| 42 | + @Resource | |
| 43 | + private Validator validator; | |
| 44 | + | |
| 45 | + @Override | |
| 46 | + public Long createChannel(PayChannelCreateReqVO reqVO) { | |
| 47 | + // 断言是否有重复的 | |
| 48 | + PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); | |
| 49 | + if (ObjectUtil.isNotNull(channelDO)) { | |
| 50 | + throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR); | |
| 51 | + } | |
| 52 | + | |
| 53 | + // 新增渠道 | |
| 54 | + PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); | |
| 55 | + settingConfigAndCheckParam(channel, reqVO.getConfig()); | |
| 56 | + channelMapper.insert(channel); | |
| 57 | + return channel.getId(); | |
| 58 | + } | |
| 59 | + | |
| 60 | + @Override | |
| 61 | + public void updateChannel(PayChannelUpdateReqVO updateReqVO) { | |
| 62 | + // 校验存在 | |
| 63 | + this.validateChannelExists(updateReqVO.getId()); | |
| 64 | + // 更新 | |
| 65 | + PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO); | |
| 66 | + settingConfigAndCheckParam(channel, updateReqVO.getConfig()); | |
| 67 | + channelMapper.updateById(channel); | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void deleteChannel(Long id) { | |
| 72 | + // 校验存在 | |
| 73 | + this.validateChannelExists(id); | |
| 74 | + // 删除 | |
| 75 | + channelMapper.deleteById(id); | |
| 76 | + } | |
| 77 | + | |
| 78 | + private void validateChannelExists(Long id) { | |
| 79 | + if (channelMapper.selectById(id) == null) { | |
| 80 | + throw exception(CHANNEL_NOT_EXISTS); | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Override | |
| 85 | + public PayChannelDO getChannel(Long id) { | |
| 86 | + return channelMapper.selectById(id); | |
| 87 | + } | |
| 88 | + | |
| 89 | + @Override | |
| 90 | + public List<PayChannelDO> getChannelList(Collection<Long> ids) { | |
| 91 | + return channelMapper.selectBatchIds(ids); | |
| 92 | + } | |
| 93 | + | |
| 94 | + @Override | |
| 95 | + public PageResult<PayChannelDO> getChannelPage(PayChannelPageReqVO pageReqVO) { | |
| 96 | + return channelMapper.selectPage(pageReqVO); | |
| 97 | + } | |
| 98 | + | |
| 99 | + @Override | |
| 100 | + public List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO) { | |
| 101 | + return channelMapper.selectList(exportReqVO); | |
| 102 | + } | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * 根据支付应用ID集合获得支付渠道列表 | |
| 106 | + * | |
| 107 | + * @param appIds 应用编号集合 | |
| 108 | + * @return 支付渠道列表 | |
| 109 | + */ | |
| 110 | + @Override | |
| 111 | + public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) { | |
| 112 | + return channelMapper.getChannelListByAppIds(appIds); | |
| 113 | + } | |
| 114 | + | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * 根据条件获取通道数量 | |
| 118 | + * | |
| 119 | + * @param merchantId 商户编号 | |
| 120 | + * @param appid 应用编号 | |
| 121 | + * @param code 通道编码 | |
| 122 | + * @return 数量 | |
| 123 | + */ | |
| 124 | + @Override | |
| 125 | + public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) { | |
| 126 | + return this.channelMapper.selectCount(merchantId, appid, code); | |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * 根据条件获取通道 | |
| 131 | + * | |
| 132 | + * @param merchantId 商户编号 | |
| 133 | + * @param appid 应用编号 | |
| 134 | + * @param code 通道编码 | |
| 135 | + * @return 数量 | |
| 136 | + */ | |
| 137 | + @Override | |
| 138 | + public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) { | |
| 139 | + return this.channelMapper.selectOne(merchantId, appid, code); | |
| 140 | + } | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * 设置渠道配置以及参数校验 | |
| 144 | + * | |
| 145 | + * @param channel 渠道 | |
| 146 | + * @param configStr 配置 | |
| 147 | + */ | |
| 148 | + private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) { | |
| 149 | + // 得到这个渠道是微信的还是支付宝的 | |
| 150 | + Class<? extends PayClientConfig> payClass = PayChannelEnum.getByCode(channel.getCode()).getConfigClass(); | |
| 151 | + if (ObjectUtil.isNull(payClass)) { | |
| 152 | + throw exception(CHANNEL_NOT_EXISTS); | |
| 153 | + } | |
| 154 | + PayClientConfig config = JSONUtil.toBean(configStr, payClass); | |
| 155 | + | |
| 156 | + // 验证参数 | |
| 157 | + config.validate(validator); | |
| 158 | + channel.setConfig(config); | |
| 159 | + } | |
| 160 | + | |
| 161 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.merchant; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 10 | + | |
| 11 | +import javax.validation.Valid; | |
| 12 | +import java.util.Collection; | |
| 13 | +import java.util.List; | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * 支付商户信息 Service 接口 | |
| 18 | + * | |
| 19 | + * @author aquan | |
| 20 | + */ | |
| 21 | +public interface PayMerchantService { | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 创建支付商户信息 | |
| 25 | + * | |
| 26 | + * @param createReqVO 创建信息 | |
| 27 | + * @return 编号 | |
| 28 | + */ | |
| 29 | + Long createMerchant(@Valid PayMerchantCreateReqVO createReqVO); | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 更新支付商户信息 | |
| 33 | + * | |
| 34 | + * @param updateReqVO 更新信息 | |
| 35 | + */ | |
| 36 | + void updateMerchant(@Valid PayMerchantUpdateReqVO updateReqVO); | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 删除支付商户信息 | |
| 40 | + * | |
| 41 | + * @param id 编号 | |
| 42 | + */ | |
| 43 | + void deleteMerchant(Long id); | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 获得支付商户信息 | |
| 47 | + * | |
| 48 | + * @param id 编号 | |
| 49 | + * @return 支付商户信息 | |
| 50 | + */ | |
| 51 | + PayMerchantDO getMerchant(Long id); | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 获得支付商户信息列表 | |
| 55 | + * | |
| 56 | + * @param ids 编号 | |
| 57 | + * @return 支付商户信息列表 | |
| 58 | + */ | |
| 59 | + List<PayMerchantDO> getMerchantList(Collection<Long> ids); | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * 获得支付商户信息分页 | |
| 63 | + * | |
| 64 | + * @param pageReqVO 分页查询 | |
| 65 | + * @return 支付商户信息分页 | |
| 66 | + */ | |
| 67 | + PageResult<PayMerchantDO> getMerchantPage(PayMerchantPageReqVO pageReqVO); | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * 获得支付商户信息列表, 用于 Excel 导出 | |
| 71 | + * | |
| 72 | + * @param exportReqVO 查询条件 | |
| 73 | + * @return 支付商户信息列表 | |
| 74 | + */ | |
| 75 | + List<PayMerchantDO> getMerchantList(PayMerchantExportReqVO exportReqVO); | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * 修改商户状态 | |
| 79 | + * | |
| 80 | + * @param id 商户编号 | |
| 81 | + * @param status 状态 | |
| 82 | + */ | |
| 83 | + void updateMerchantStatus(Long id, Integer status); | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 根据商户名称模糊查询商户集合 | |
| 87 | + * | |
| 88 | + * @param merchantName 商户名称 | |
| 89 | + * @return 商户集合 | |
| 90 | + */ | |
| 91 | + List<PayMerchantDO> getMerchantListByName(String merchantName); | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * 获得指定编号的商户 Map | |
| 95 | + * | |
| 96 | + * @param merchantIds 商户编号数组 | |
| 97 | + * @return 商户 Map | |
| 98 | + */ | |
| 99 | + default Map<Long, PayMerchantDO> getMerchantMap(Collection<Long> merchantIds) { | |
| 100 | + List<PayMerchantDO> list = this.getMerchantList(merchantIds); | |
| 101 | + return CollectionUtils.convertMap(list, PayMerchantDO::getId); | |
| 102 | + } | |
| 103 | + | |
| 104 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.date.DateUtil; | |
| 4 | +import cn.hutool.core.util.ObjectUtil; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; | |
| 11 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; | |
| 12 | +import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; | |
| 13 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 15 | +import com.google.common.annotations.VisibleForTesting; | |
| 16 | +import org.springframework.stereotype.Service; | |
| 17 | +import org.springframework.validation.annotation.Validated; | |
| 18 | + | |
| 19 | +import javax.annotation.Resource; | |
| 20 | +import java.time.LocalDateTime; | |
| 21 | +import java.util.Collection; | |
| 22 | +import java.util.List; | |
| 23 | + | |
| 24 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_EXIST_APP_CANT_DELETE; | |
| 25 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS; | |
| 26 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * 支付商户信息 Service 实现类 | |
| 30 | + * | |
| 31 | + * @author aquan | |
| 32 | + */ | |
| 33 | +@Service | |
| 34 | +@Validated | |
| 35 | +public class PayMerchantServiceImpl implements PayMerchantService { | |
| 36 | + | |
| 37 | + @Resource | |
| 38 | + private PayMerchantMapper merchantMapper; | |
| 39 | + | |
| 40 | + @Resource | |
| 41 | + private PayAppMapper appMapper; | |
| 42 | + | |
| 43 | + @Override | |
| 44 | + public Long createMerchant(PayMerchantCreateReqVO createReqVO) { | |
| 45 | + // 插入 | |
| 46 | + PayMerchantDO merchant = PayMerchantConvert.INSTANCE.convert(createReqVO); | |
| 47 | + merchant.setNo(this.generateMerchantNo()); | |
| 48 | + merchantMapper.insert(merchant); | |
| 49 | + // 返回 | |
| 50 | + return merchant.getId(); | |
| 51 | + } | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public void updateMerchant(PayMerchantUpdateReqVO updateReqVO) { | |
| 55 | + // 校验存在 | |
| 56 | + this.validateMerchantExists(updateReqVO.getId()); | |
| 57 | + // 更新 | |
| 58 | + PayMerchantDO updateObj = PayMerchantConvert.INSTANCE.convert(updateReqVO); | |
| 59 | + merchantMapper.updateById(updateObj); | |
| 60 | + } | |
| 61 | + | |
| 62 | + @Override | |
| 63 | + public void deleteMerchant(Long id) { | |
| 64 | + // 校验 | |
| 65 | + this.validateMerchantExists(id); | |
| 66 | + this.validateAppExists(id); | |
| 67 | + // 删除 | |
| 68 | + merchantMapper.deleteById(id); | |
| 69 | + } | |
| 70 | + | |
| 71 | + @Override | |
| 72 | + public PayMerchantDO getMerchant(Long id) { | |
| 73 | + return merchantMapper.selectById(id); | |
| 74 | + } | |
| 75 | + | |
| 76 | + @Override | |
| 77 | + public List<PayMerchantDO> getMerchantList(Collection<Long> ids) { | |
| 78 | + return merchantMapper.selectBatchIds(ids); | |
| 79 | + } | |
| 80 | + | |
| 81 | + @Override | |
| 82 | + public PageResult<PayMerchantDO> getMerchantPage(PayMerchantPageReqVO pageReqVO) { | |
| 83 | + return merchantMapper.selectPage(pageReqVO); | |
| 84 | + } | |
| 85 | + | |
| 86 | + @Override | |
| 87 | + public List<PayMerchantDO> getMerchantList(PayMerchantExportReqVO exportReqVO) { | |
| 88 | + return merchantMapper.selectList(exportReqVO); | |
| 89 | + } | |
| 90 | + | |
| 91 | + @Override | |
| 92 | + public void updateMerchantStatus(Long id, Integer status) { | |
| 93 | + // 校验商户存在 | |
| 94 | + this.checkMerchantExists(id); | |
| 95 | + // 更新状态 | |
| 96 | + PayMerchantDO merchant = new PayMerchantDO(); | |
| 97 | + merchant.setId(id); | |
| 98 | + merchant.setStatus(status); | |
| 99 | + merchantMapper.updateById(merchant); | |
| 100 | + } | |
| 101 | + | |
| 102 | + @Override | |
| 103 | + public List<PayMerchantDO> getMerchantListByName(String merchantName) { | |
| 104 | + return this.merchantMapper.getMerchantListByName(merchantName); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @VisibleForTesting | |
| 108 | + public void checkMerchantExists(Long id) { | |
| 109 | + if (id == null) { | |
| 110 | + return; | |
| 111 | + } | |
| 112 | + PayMerchantDO merchant = merchantMapper.selectById(id); | |
| 113 | + if (merchant == null) { | |
| 114 | + throw exception(PAY_MERCHANT_NOT_EXISTS); | |
| 115 | + } | |
| 116 | + } | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * 校验商户是否存在 | |
| 120 | + * | |
| 121 | + * @param id 商户 ID | |
| 122 | + */ | |
| 123 | + private void validateMerchantExists(Long id) { | |
| 124 | + if (ObjectUtil.isNull(merchantMapper.selectById(id))) { | |
| 125 | + throw exception(PAY_MERCHANT_NOT_EXISTS); | |
| 126 | + } | |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * 校验商户是否还存在支付应用 | |
| 131 | + * | |
| 132 | + * @param id 商户ID | |
| 133 | + */ | |
| 134 | + private void validateAppExists(Long id) { | |
| 135 | + if (appMapper.selectCount(id) > 0) { | |
| 136 | + throw exception(PAY_MERCHANT_EXIST_APP_CANT_DELETE); | |
| 137 | + } | |
| 138 | + } | |
| 139 | + | |
| 140 | + // TODO @芋艿:后续增加下合适的算法 | |
| 141 | + /** | |
| 142 | + * 根据年月日时分秒毫秒生成商户号 | |
| 143 | + * | |
| 144 | + * @return 商户号 | |
| 145 | + */ | |
| 146 | + private String generateMerchantNo() { | |
| 147 | + return "M" + DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS"); | |
| 148 | + } | |
| 149 | + | |
| 150 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderExtensionService.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 5 | + | |
| 6 | +import java.util.Collection; | |
| 7 | +import java.util.List; | |
| 8 | +import java.util.Map; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 支付订单 Service 接口 | |
| 12 | + * | |
| 13 | + * @author aquan | |
| 14 | + */ | |
| 15 | +public interface PayOrderExtensionService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 获得支付订单 | |
| 19 | + * | |
| 20 | + * @param id 编号 | |
| 21 | + * @return 支付订单 | |
| 22 | + */ | |
| 23 | + PayOrderExtensionDO getOrderExtension(Long id); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 获得支付订单 | |
| 27 | + * 列表 | |
| 28 | + * | |
| 29 | + * @param ids 编号 | |
| 30 | + * @return 支付订单 | |
| 31 | + * 列表 | |
| 32 | + */ | |
| 33 | + List<PayOrderExtensionDO> getOrderExtensionList(Collection<Long> ids); | |
| 34 | + | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 根据订单成功的 扩展订单ID 查询所有的扩展订单转 成 map 返回 | |
| 38 | + * | |
| 39 | + * @param successExtensionIdList 订单 ID 集合 | |
| 40 | + * @return 订单扩展 map 集合 | |
| 41 | + */ | |
| 42 | + default Map<Long, PayOrderExtensionDO> getOrderExtensionMap(Collection<Long> successExtensionIdList) { | |
| 43 | + List<PayOrderExtensionDO> list = this.getOrderExtensionList(successExtensionIdList); | |
| 44 | + return CollectionUtils.convertMap(list, PayOrderExtensionDO::getId); | |
| 45 | + } | |
| 46 | + | |
| 47 | + | |
| 48 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderService.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 8 | + | |
| 9 | +import java.util.Collection; | |
| 10 | +import java.util.List; | |
| 11 | +import java.util.Map; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 支付订单 Service 接口 | |
| 15 | + * | |
| 16 | + * @author aquan | |
| 17 | + */ | |
| 18 | +public interface PayOrderService { | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 获得支付订单 | |
| 22 | + * | |
| 23 | + * @param id 编号 | |
| 24 | + * @return 支付订单 | |
| 25 | + */ | |
| 26 | + PayOrderDO getOrder(Long id); | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 获得支付订单 | |
| 30 | + * 分页 | |
| 31 | + * | |
| 32 | + * @param pageReqVO 分页查询 | |
| 33 | + * @return 支付订单 | |
| 34 | + * 分页 | |
| 35 | + */ | |
| 36 | + PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO); | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 获得支付订单 | |
| 40 | + * 列表, 用于 Excel 导出 | |
| 41 | + * | |
| 42 | + * @param exportReqVO 查询条件 | |
| 43 | + * @return 支付订单 | |
| 44 | + * 列表 | |
| 45 | + */ | |
| 46 | + List<PayOrderDO> getOrderList(PayOrderExportReqVO exportReqVO); | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 根据 ID 集合获取只包含商品名称的订单集合 | |
| 50 | + * | |
| 51 | + * @param idList 订单 ID 集合 | |
| 52 | + * @return 只包含商品名称的订单集合 | |
| 53 | + */ | |
| 54 | + List<PayOrderDO> getOrderSubjectList(Collection<Long> idList); | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 根据订单 ID 集合获取订单商品名称Map集合 | |
| 58 | + * | |
| 59 | + * @param idList 订单 ID 集合 | |
| 60 | + * @return 订单商品 map 集合 | |
| 61 | + */ | |
| 62 | + default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> idList) { | |
| 63 | + List<PayOrderDO> list = getOrderSubjectList(idList); | |
| 64 | + return CollectionUtils.convertMap(list, PayOrderDO::getId); | |
| 65 | + } | |
| 66 | + | |
| 67 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayRefundService.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 7 | + | |
| 8 | +import java.util.List; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 退款订单 Service 接口 | |
| 12 | + * | |
| 13 | + * @author aquan | |
| 14 | + */ | |
| 15 | +public interface PayRefundService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 获得退款订单 | |
| 19 | + * | |
| 20 | + * @param id 编号 | |
| 21 | + * @return 退款订单 | |
| 22 | + */ | |
| 23 | + PayRefundDO getRefund(Long id); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 获得退款订单分页 | |
| 27 | + * | |
| 28 | + * @param pageReqVO 分页查询 | |
| 29 | + * @return 退款订单分页 | |
| 30 | + */ | |
| 31 | + PageResult<PayRefundDO> getRefundPage(PayRefundPageReqVO pageReqVO); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 获得退款订单列表, 用于 Excel 导出 | |
| 35 | + * | |
| 36 | + * @param exportReqVO 查询条件 | |
| 37 | + * @return 退款订单列表 | |
| 38 | + */ | |
| 39 | + List<PayRefundDO> getRefundList(PayRefundExportReqVO exportReqVO); | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderExtensionServiceImpl.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderExtensionMapper; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderExtensionService; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; | |
| 6 | +import org.springframework.stereotype.Service; | |
| 7 | +import org.springframework.validation.annotation.Validated; | |
| 8 | + | |
| 9 | +import javax.annotation.Resource; | |
| 10 | +import java.util.Collection; | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 支付订单 Service 实现类 | |
| 15 | + * | |
| 16 | + * @author aquan | |
| 17 | + */ | |
| 18 | +@Service | |
| 19 | +@Validated | |
| 20 | +public class PayOrderExtensionServiceImpl implements PayOrderExtensionService { | |
| 21 | + | |
| 22 | + @Resource | |
| 23 | + private PayOrderExtensionMapper orderExtensionMapper; | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public PayOrderExtensionDO getOrderExtension(Long id) { | |
| 27 | + return orderExtensionMapper.selectById(id); | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public List<PayOrderExtensionDO> getOrderExtensionList(Collection<Long> ids) { | |
| 32 | + return orderExtensionMapper.selectBatchIds(ids); | |
| 33 | + } | |
| 34 | + | |
| 35 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderServiceImpl.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import org.springframework.stereotype.Service; | |
| 10 | +import org.springframework.validation.annotation.Validated; | |
| 11 | + | |
| 12 | +import javax.annotation.Resource; | |
| 13 | +import java.util.Collection; | |
| 14 | +import java.util.List; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * 支付订单 Service 实现类 | |
| 18 | + * | |
| 19 | + * @author aquan | |
| 20 | + */ | |
| 21 | +@Service | |
| 22 | +@Validated | |
| 23 | +public class PayOrderServiceImpl implements PayOrderService { | |
| 24 | + | |
| 25 | + @Resource | |
| 26 | + private PayOrderMapper orderMapper; | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public PayOrderDO getOrder(Long id) { | |
| 30 | + return orderMapper.selectById(id); | |
| 31 | + } | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO) { | |
| 35 | + return orderMapper.selectPage(pageReqVO); | |
| 36 | + } | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public List<PayOrderDO> getOrderList(PayOrderExportReqVO exportReqVO) { | |
| 40 | + return orderMapper.selectList(exportReqVO); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 根据 ID 集合获取只包含商品名称的订单集合 | |
| 45 | + * | |
| 46 | + * @param idList 订单 ID 集合 | |
| 47 | + * @return 只包含商品名称的订单集合 | |
| 48 | + */ | |
| 49 | + @Override | |
| 50 | + public List<PayOrderDO> getOrderSubjectList(Collection<Long> idList) { | |
| 51 | + return orderMapper.findByIdListQueryOrderSubject(idList); | |
| 52 | + } | |
| 53 | + | |
| 54 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayRefundServiceImpl.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayRefundService; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import org.springframework.stereotype.Service; | |
| 10 | +import org.springframework.validation.annotation.Validated; | |
| 11 | + | |
| 12 | +import javax.annotation.Resource; | |
| 13 | +import java.util.List; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 退款订单 Service 实现类 | |
| 17 | + * | |
| 18 | + * @author aquan | |
| 19 | + */ | |
| 20 | +@Service | |
| 21 | +@Validated | |
| 22 | +public class PayRefundServiceImpl implements PayRefundService { | |
| 23 | + | |
| 24 | + @Resource | |
| 25 | + private PayRefundMapper refundMapper; | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public PayRefundDO getRefund(Long id) { | |
| 29 | + return refundMapper.selectById(id); | |
| 30 | + } | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public PageResult<PayRefundDO> getRefundPage(PayRefundPageReqVO pageReqVO) { | |
| 34 | + return refundMapper.selectPage(pageReqVO); | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Override | |
| 38 | + public List<PayRefundDO> getRefundList(PayRefundExportReqVO exportReqVO) { | |
| 39 | + return refundMapper.selectList(exportReqVO); | |
| 40 | + } | |
| 41 | + | |
| 42 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java
| ... | ... | @@ -22,6 +22,31 @@ public interface SysDictTypeConstants { |
| 22 | 22 | String SMS_SEND_STATUS = "sys_sms_send_status"; // 短信发送状态 |
| 23 | 23 | String SMS_RECEIVE_STATUS = "sys_sms_receive_status"; // 短信接收状态 |
| 24 | 24 | |
| 25 | + /** | |
| 26 | + * 支付-订单-订单状态 | |
| 27 | + */ | |
| 28 | + String PAY_ORDER_STATUS = "pay_order_status"; | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 支付-订单-订单回调商户状态 | |
| 32 | + */ | |
| 33 | + String PAY_ORDER_NOTIFY_STATUS = "pay_order_notify_status"; | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 支付-订单-订单退款状态 | |
| 37 | + */ | |
| 38 | + String PAY_ORDER_REFUND_STATUS = "pay_order_refund_status"; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 支付-退款订单-退款状态 | |
| 42 | + */ | |
| 43 | + String PAY_REFUND_ORDER_STATUS = "pay_refund_order_status"; | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 支付-退款订单-退款类别 | |
| 47 | + */ | |
| 48 | + String PAY_REFUND_ORDER_TYPE = "pay_refund_order_type"; | |
| 49 | + | |
| 25 | 50 | String BPM_TASK_ASSIGN_RULE_TYPE = "bpm_task_assign_rule_type"; // 任务分配规则类型 |
| 26 | 51 | String BPM_TASK_ASSIGN_SCRIPT = "bpm_task_assign_script"; // 任务分配自定义脚本 |
| 27 | 52 | ... | ... |
yudao-admin-server/src/main/resources/application-local.yaml
| ... | ... | @@ -183,6 +183,7 @@ yudao: |
| 183 | 183 | - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 |
| 184 | 184 | pay: |
| 185 | 185 | pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify |
| 186 | + pay-return-url: http://niubi.natapp1.cc/api/pay/order/return | |
| 186 | 187 | refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify |
| 187 | 188 | demo: false # 关闭演示模式 |
| 188 | 189 | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java
| ... | ... | @@ -31,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.*; |
| 31 | 31 | import static org.mockito.ArgumentMatchers.eq; |
| 32 | 32 | import static org.mockito.Mockito.when; |
| 33 | 33 | |
| 34 | -class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { | |
| 34 | +public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { | |
| 35 | 35 | |
| 36 | 36 | @InjectMocks |
| 37 | 37 | private BpmUserTaskActivitiBehavior behavior; | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.app; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.RandomUtil; | |
| 4 | +import cn.iocoder.yudao.adminserver.BaseDbUnitTest; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; | |
| 11 | +import cn.iocoder.yudao.adminserver.modules.pay.service.app.impl.PayAppServiceImpl; | |
| 12 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 13 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 14 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 15 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 16 | +import org.junit.jupiter.api.Test; | |
| 17 | +import org.mockito.Mockito; | |
| 18 | +import org.springframework.boot.test.mock.mockito.MockBean; | |
| 19 | +import org.springframework.context.annotation.Import; | |
| 20 | + | |
| 21 | +import javax.annotation.Resource; | |
| 22 | +import java.util.Collections; | |
| 23 | +import java.util.List; | |
| 24 | + | |
| 25 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_APP_NOT_FOUND; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; | |
| 27 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 28 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | |
| 29 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 30 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | |
| 31 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 32 | +import static org.junit.jupiter.api.Assertions.*; | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * {@link PayAppServiceImpl} 的单元测试类 | |
| 36 | + * | |
| 37 | + * @author 芋艿 | |
| 38 | + */ | |
| 39 | +@Import(PayAppServiceImpl.class) | |
| 40 | +public class PayAppServiceTest extends BaseDbUnitTest { | |
| 41 | + | |
| 42 | + @Resource | |
| 43 | + private PayAppServiceImpl appService; | |
| 44 | + | |
| 45 | + @Resource | |
| 46 | + private PayAppMapper appMapper; | |
| 47 | + | |
| 48 | + @MockBean(name = "payMerchantMapper") | |
| 49 | + private PayMerchantMapper payMerchantMapper; | |
| 50 | + | |
| 51 | + @Test | |
| 52 | + public void testCreateApp_success() { | |
| 53 | + // 准备参数 | |
| 54 | + PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class, o -> | |
| 55 | + o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); | |
| 56 | + | |
| 57 | + // 调用 | |
| 58 | + Long appId = appService.createApp(reqVO); | |
| 59 | + // 断言 | |
| 60 | + assertNotNull(appId); | |
| 61 | + // 校验记录的属性是否正确 | |
| 62 | + PayAppDO app = appMapper.selectById(appId); | |
| 63 | + assertPojoEquals(reqVO, app); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @Test | |
| 67 | + public void testUpdateApp_success() { | |
| 68 | + // mock 数据 | |
| 69 | + PayAppDO dbApp = randomPojo(PayAppDO.class, o -> | |
| 70 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus())); | |
| 71 | + appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据 | |
| 72 | + // 准备参数 | |
| 73 | + PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> { | |
| 74 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 75 | + o.setId(dbApp.getId()); // 设置更新的 ID | |
| 76 | + }); | |
| 77 | + | |
| 78 | + // 调用 | |
| 79 | + appService.updateApp(reqVO); | |
| 80 | + // 校验是否更新正确 | |
| 81 | + PayAppDO app = appMapper.selectById(reqVO.getId()); // 获取最新的 | |
| 82 | + assertPojoEquals(reqVO, app); | |
| 83 | + } | |
| 84 | + | |
| 85 | + @Test | |
| 86 | + public void testUpdateApp_notExists() { | |
| 87 | + // 准备参数 | |
| 88 | + PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> | |
| 89 | + o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); | |
| 90 | + // 调用, 并断言异常 | |
| 91 | + assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND); | |
| 92 | + } | |
| 93 | + | |
| 94 | + @Test | |
| 95 | + public void testDeleteApp_success() { | |
| 96 | + // mock 数据 | |
| 97 | + PayAppDO dbApp = randomPojo(PayAppDO.class, o -> | |
| 98 | + o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); | |
| 99 | + appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据 | |
| 100 | + // 准备参数 | |
| 101 | + Long id = dbApp.getId(); | |
| 102 | + | |
| 103 | + // 调用 | |
| 104 | + appService.deleteApp(id); | |
| 105 | + // 校验数据不存在了 | |
| 106 | + assertNull(appMapper.selectById(id)); | |
| 107 | + } | |
| 108 | + | |
| 109 | + @Test | |
| 110 | + public void testDeleteApp_notExists() { | |
| 111 | + // 准备参数 | |
| 112 | + Long id = randomLongId(); | |
| 113 | + | |
| 114 | + // 调用, 并断言异常 | |
| 115 | + assertServiceException(() -> appService.deleteApp(id), PAY_APP_NOT_FOUND); | |
| 116 | + } | |
| 117 | + | |
| 118 | + @Test | |
| 119 | + public void testGetAppPage() { | |
| 120 | + Long merchantId = 1L; | |
| 121 | + Long mismatchMerchantId = 2L; | |
| 122 | + | |
| 123 | + // mock 数据 | |
| 124 | + PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到 | |
| 125 | + o.setName("灿灿姐的杂货铺"); | |
| 126 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 127 | + o.setRemark("敏敏姐的小卖铺"); | |
| 128 | + o.setPayNotifyUrl("https://www.hc.com"); | |
| 129 | + o.setRefundNotifyUrl("https://www.xm.com"); | |
| 130 | + o.setMerchantId(merchantId); | |
| 131 | + o.setCreateTime(buildTime(2021,11,20)); | |
| 132 | + }); | |
| 133 | + | |
| 134 | + // mock 数据 | |
| 135 | + PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到 | |
| 136 | + o.setId(merchantId); | |
| 137 | + o.setNo("M1008611"); | |
| 138 | + o.setName("灿哥的杂货铺"); | |
| 139 | + o.setShortName("灿灿子"); | |
| 140 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 141 | + o.setRemark("灿哥的杂货铺"); | |
| 142 | + o.setCreateTime(buildTime(2021,11,3)); | |
| 143 | + }); | |
| 144 | + | |
| 145 | + Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName())) | |
| 146 | + .thenReturn(Collections.singletonList(dbMerchant)); | |
| 147 | + | |
| 148 | + appMapper.insert(dbApp); | |
| 149 | + // 测试 name 不匹配 | |
| 150 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setName("敏敏姐的杂货铺"))); | |
| 151 | + // 测试 status 不匹配 | |
| 152 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); | |
| 153 | + // 测试 remark 不匹配 | |
| 154 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRemark("灿灿姐的小卖部"))); | |
| 155 | + // 测试 payNotifyUrl 不匹配 | |
| 156 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setPayNotifyUrl("xm.com"))); | |
| 157 | + // 测试 refundNotifyUrl 不匹配 | |
| 158 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRefundNotifyUrl("hc.com"))); | |
| 159 | + // 测试 merchantId 不匹配 | |
| 160 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setMerchantId(mismatchMerchantId))); | |
| 161 | + // 测试 createTime 不匹配 | |
| 162 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21)))); | |
| 163 | + // 准备参数 | |
| 164 | + PayAppPageReqVO reqVO = new PayAppPageReqVO(); | |
| 165 | + reqVO.setName("灿灿姐的杂货铺"); | |
| 166 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 167 | + reqVO.setRemark("敏敏姐的小卖铺"); | |
| 168 | + reqVO.setPayNotifyUrl("https://www.hc.com"); | |
| 169 | + reqVO.setRefundNotifyUrl("https://www.xm.com"); | |
| 170 | + reqVO.setMerchantName(dbMerchant.getName()); | |
| 171 | + reqVO.setBeginCreateTime(buildTime(2021,11,19)); | |
| 172 | + reqVO.setEndCreateTime(buildTime(2021,11,21)); | |
| 173 | + | |
| 174 | + // 调用 | |
| 175 | + PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO); | |
| 176 | + // 断言 | |
| 177 | + assertEquals(1, pageResult.getTotal()); | |
| 178 | + assertEquals(1, pageResult.getList().size()); | |
| 179 | + assertPojoEquals(dbApp, pageResult.getList().get(0)); | |
| 180 | + } | |
| 181 | + | |
| 182 | + @Test // TODO 请修改 null 为需要的值 | |
| 183 | + public void testGetAppList() { | |
| 184 | + Long merchantId = 1L; | |
| 185 | + Long mismatchMerchantId = 2L; | |
| 186 | + | |
| 187 | + // mock 数据 | |
| 188 | + PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到 | |
| 189 | + o.setName("灿灿姐的杂货铺"); | |
| 190 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 191 | + o.setRemark("敏敏姐的小卖铺"); | |
| 192 | + o.setPayNotifyUrl("https://www.hc.com"); | |
| 193 | + o.setRefundNotifyUrl("https://www.xm.com"); | |
| 194 | + o.setMerchantId(merchantId); | |
| 195 | + o.setCreateTime(buildTime(2021,11,20)); | |
| 196 | + }); | |
| 197 | + | |
| 198 | + // mock 数据 | |
| 199 | + PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到 | |
| 200 | + o.setId(merchantId); | |
| 201 | + o.setNo("M1008611"); | |
| 202 | + o.setName("灿哥的杂货铺"); | |
| 203 | + o.setShortName("灿灿子"); | |
| 204 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 205 | + o.setRemark("灿哥的杂货铺"); | |
| 206 | + o.setCreateTime(buildTime(2021,11,3)); | |
| 207 | + }); | |
| 208 | + | |
| 209 | + Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName())) | |
| 210 | + .thenReturn(Collections.singletonList(dbMerchant)); | |
| 211 | + | |
| 212 | + appMapper.insert(dbApp); | |
| 213 | + // 测试 name 不匹配 | |
| 214 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setName("敏敏姐的杂货铺"))); | |
| 215 | + // 测试 status 不匹配 | |
| 216 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); | |
| 217 | + // 测试 remark 不匹配 | |
| 218 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRemark("灿灿姐的小卖部"))); | |
| 219 | + // 测试 payNotifyUrl 不匹配 | |
| 220 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setPayNotifyUrl("xm.com"))); | |
| 221 | + // 测试 refundNotifyUrl 不匹配 | |
| 222 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRefundNotifyUrl("hc.com"))); | |
| 223 | + // 测试 merchantId 不匹配 | |
| 224 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setMerchantId(mismatchMerchantId))); | |
| 225 | + // 测试 createTime 不匹配 | |
| 226 | + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21)))); | |
| 227 | + // 准备参数 | |
| 228 | + PayAppExportReqVO reqVO = new PayAppExportReqVO(); | |
| 229 | + reqVO.setName("灿灿姐的杂货铺"); | |
| 230 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 231 | + reqVO.setRemark("敏敏姐的小卖铺"); | |
| 232 | + reqVO.setPayNotifyUrl("https://www.hc.com"); | |
| 233 | + reqVO.setRefundNotifyUrl("https://www.xm.com"); | |
| 234 | + reqVO.setMerchantName(dbMerchant.getName()); | |
| 235 | + reqVO.setBeginCreateTime(buildTime(2021,11,19)); | |
| 236 | + reqVO.setEndCreateTime(buildTime(2021,11,21)); | |
| 237 | + | |
| 238 | + // 调用 | |
| 239 | + List<PayAppDO> list = appService.getAppList(reqVO); | |
| 240 | + // 断言 | |
| 241 | + assertEquals(1, list.size()); | |
| 242 | + assertPojoEquals(dbApp, list.get(0)); | |
| 243 | + } | |
| 244 | + | |
| 245 | +} | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelConfig.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.channel; | |
| 2 | + | |
| 3 | +import org.springframework.context.annotation.Bean; | |
| 4 | +import org.springframework.context.annotation.Configuration; | |
| 5 | + | |
| 6 | +import javax.validation.Validation; | |
| 7 | +import javax.validation.Validator; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 用于初始化 validator Bean 对象 | |
| 11 | + * @author aquan | |
| 12 | + */ | |
| 13 | +@Configuration | |
| 14 | +public class PayChannelConfig { | |
| 15 | + | |
| 16 | + @Bean | |
| 17 | + public Validator validator(){ | |
| 18 | + return Validation.buildDefaultValidatorFactory().getValidator(); | |
| 19 | + } | |
| 20 | +} | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.channel; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl; | |
| 10 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 11 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 12 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 13 | +import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; | |
| 14 | +import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; | |
| 15 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 16 | +import com.alibaba.fastjson.JSON; | |
| 17 | +import org.junit.jupiter.api.Test; | |
| 18 | +import org.springframework.context.annotation.Import; | |
| 19 | + | |
| 20 | +import javax.annotation.Resource; | |
| 21 | +import java.util.List; | |
| 22 | + | |
| 23 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 26 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | |
| 27 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 28 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | |
| 29 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 30 | +import static org.junit.jupiter.api.Assertions.*; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * {@link PayChannelServiceImpl} 的单元测试类 | |
| 34 | + * | |
| 35 | + * @author 芋艿 | |
| 36 | + */ | |
| 37 | +@Import({ | |
| 38 | + PayChannelServiceImpl.class, | |
| 39 | + PayChannelConfig.class | |
| 40 | +}) | |
| 41 | +public class PayChannelServiceTest extends BaseDbUnitTest { | |
| 42 | + | |
| 43 | + @Resource | |
| 44 | + private PayChannelServiceImpl channelService; | |
| 45 | + | |
| 46 | + @Resource | |
| 47 | + private PayChannelMapper channelMapper; | |
| 48 | + | |
| 49 | + @Test | |
| 50 | + public void testCreateWechatVersion2Channel_success() { | |
| 51 | + // 准备参数 | |
| 52 | + | |
| 53 | + WXPayClientConfig v2Config = getV2Config(); | |
| 54 | + PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { | |
| 55 | + o.setCode(PayChannelEnum.WX_PUB.getCode()); | |
| 56 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 57 | + o.setConfig(JSON.toJSONString(v2Config)); | |
| 58 | + }); | |
| 59 | + | |
| 60 | + // 调用 | |
| 61 | + Long channelId = channelService.createChannel(reqVO); | |
| 62 | + // 断言 | |
| 63 | + assertNotNull(channelId); | |
| 64 | + // 校验记录的属性是否正确 | |
| 65 | + PayChannelDO channel = channelMapper.selectById(channelId); | |
| 66 | + assertPojoEquals(reqVO, channel, "config"); | |
| 67 | + // 关于config 对象应该拿出来重新对比 | |
| 68 | + assertPojoEquals(v2Config, channel.getConfig()); | |
| 69 | + | |
| 70 | + } | |
| 71 | + | |
| 72 | + @Test | |
| 73 | + public void testCreateWechatVersion3Channel_success() { | |
| 74 | + // 准备参数 | |
| 75 | + WXPayClientConfig v3Config = getV3Config(); | |
| 76 | + PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { | |
| 77 | + o.setCode(PayChannelEnum.WX_PUB.getCode()); | |
| 78 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 79 | + o.setConfig(JSON.toJSONString(v3Config)); | |
| 80 | + }); | |
| 81 | + | |
| 82 | + // 调用 | |
| 83 | + Long channelId = channelService.createChannel(reqVO); | |
| 84 | + // 断言 | |
| 85 | + assertNotNull(channelId); | |
| 86 | + // 校验记录的属性是否正确 | |
| 87 | + PayChannelDO channel = channelMapper.selectById(channelId); | |
| 88 | + assertPojoEquals(reqVO, channel, "config"); | |
| 89 | + // 关于config 对象应该拿出来重新对比 | |
| 90 | + assertPojoEquals(v3Config, channel.getConfig()); | |
| 91 | + } | |
| 92 | + | |
| 93 | + @Test | |
| 94 | + public void testCreateAliPayPublicKeyChannel_success() { | |
| 95 | + // 准备参数 | |
| 96 | + | |
| 97 | + AlipayPayClientConfig payClientConfig = getPublicKeyConfig(); | |
| 98 | + PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { | |
| 99 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 100 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 101 | + o.setConfig(JSON.toJSONString(payClientConfig)); | |
| 102 | + }); | |
| 103 | + | |
| 104 | + // 调用 | |
| 105 | + Long channelId = channelService.createChannel(reqVO); | |
| 106 | + // 断言 | |
| 107 | + assertNotNull(channelId); | |
| 108 | + // 校验记录的属性是否正确 | |
| 109 | + PayChannelDO channel = channelMapper.selectById(channelId); | |
| 110 | + assertPojoEquals(reqVO, channel, "config"); | |
| 111 | + // 关于config 对象应该拿出来重新对比 | |
| 112 | + assertPojoEquals(payClientConfig, channel.getConfig()); | |
| 113 | + | |
| 114 | + } | |
| 115 | + | |
| 116 | + @Test | |
| 117 | + public void testCreateAliPayCertificateChannel_success() { | |
| 118 | + // 准备参数 | |
| 119 | + | |
| 120 | + AlipayPayClientConfig payClientConfig = getCertificateConfig(); | |
| 121 | + PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { | |
| 122 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 123 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 124 | + o.setConfig(JSON.toJSONString(payClientConfig)); | |
| 125 | + }); | |
| 126 | + | |
| 127 | + // 调用 | |
| 128 | + Long channelId = channelService.createChannel(reqVO); | |
| 129 | + // 断言 | |
| 130 | + assertNotNull(channelId); | |
| 131 | + // 校验记录的属性是否正确 | |
| 132 | + PayChannelDO channel = channelMapper.selectById(channelId); | |
| 133 | + assertPojoEquals(reqVO, channel, "config"); | |
| 134 | + // 关于config 对象应该拿出来重新对比 | |
| 135 | + assertPojoEquals(payClientConfig, channel.getConfig()); | |
| 136 | + } | |
| 137 | + | |
| 138 | + @Test | |
| 139 | + public void testUpdateChannel_success() { | |
| 140 | + // mock 数据 | |
| 141 | + AlipayPayClientConfig payClientConfig = getCertificateConfig(); | |
| 142 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { | |
| 143 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 144 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 145 | + o.setConfig(payClientConfig); | |
| 146 | + }); | |
| 147 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | |
| 148 | + // 准备参数 | |
| 149 | + AlipayPayClientConfig payClientPublicKeyConfig = getPublicKeyConfig(); | |
| 150 | + PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> { | |
| 151 | + o.setCode(dbChannel.getCode()); | |
| 152 | + o.setStatus(dbChannel.getStatus()); | |
| 153 | + o.setConfig(JSON.toJSONString(payClientPublicKeyConfig)); | |
| 154 | + o.setId(dbChannel.getId()); // 设置更新的 ID | |
| 155 | + }); | |
| 156 | + | |
| 157 | + // 调用 | |
| 158 | + channelService.updateChannel(reqVO); | |
| 159 | + // 校验是否更新正确 | |
| 160 | + PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的 | |
| 161 | + assertPojoEquals(reqVO, channel, "config"); | |
| 162 | + assertPojoEquals(payClientPublicKeyConfig, channel.getConfig()); | |
| 163 | + } | |
| 164 | + | |
| 165 | + @Test | |
| 166 | + public void testUpdateChannel_notExists() { | |
| 167 | + // 准备参数 | |
| 168 | + AlipayPayClientConfig payClientPublicKeyConfig = getPublicKeyConfig(); | |
| 169 | + PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> { | |
| 170 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 171 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 172 | + o.setConfig(JSON.toJSONString(payClientPublicKeyConfig)); | |
| 173 | + }); | |
| 174 | + | |
| 175 | + // 调用, 并断言异常 | |
| 176 | + assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS); | |
| 177 | + } | |
| 178 | + | |
| 179 | + @Test | |
| 180 | + public void testDeleteChannel_success() { | |
| 181 | + // mock 数据 | |
| 182 | + AlipayPayClientConfig payClientConfig = getCertificateConfig(); | |
| 183 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { | |
| 184 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 185 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 186 | + o.setConfig(payClientConfig); | |
| 187 | + }); | |
| 188 | + channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据 | |
| 189 | + // 准备参数 | |
| 190 | + Long id = dbChannel.getId(); | |
| 191 | + | |
| 192 | + // 调用 | |
| 193 | + channelService.deleteChannel(id); | |
| 194 | + // 校验数据不存在了 | |
| 195 | + assertNull(channelMapper.selectById(id)); | |
| 196 | + } | |
| 197 | + | |
| 198 | + @Test | |
| 199 | + public void testDeleteChannel_notExists() { | |
| 200 | + // 准备参数 | |
| 201 | + Long id = randomLongId(); | |
| 202 | + | |
| 203 | + // 调用, 并断言异常 | |
| 204 | + assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS); | |
| 205 | + } | |
| 206 | + | |
| 207 | + @Test // TODO 请修改 null 为需要的值 | |
| 208 | + public void testGetChannelPage() { | |
| 209 | + // mock 数据 | |
| 210 | + AlipayPayClientConfig payClientConfig = getCertificateConfig(); | |
| 211 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到 | |
| 212 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 213 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 214 | + o.setRemark("灿灿子的支付渠道"); | |
| 215 | + o.setFeeRate(0.03); | |
| 216 | + o.setMerchantId(1L); | |
| 217 | + o.setAppId(1L); | |
| 218 | + o.setConfig(payClientConfig); | |
| 219 | + o.setCreateTime(buildTime(2021,11,20)); | |
| 220 | + }); | |
| 221 | + channelMapper.insert(dbChannel); | |
| 222 | + // 执行拷贝的时候会出现异常,所以在插入后要重置为null 后续在写入新的 | |
| 223 | + dbChannel.setConfig(null); | |
| 224 | + // 测试 code 不匹配 | |
| 225 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 226 | + o.setConfig(payClientConfig); | |
| 227 | + o.setCode(PayChannelEnum.WX_PUB.getCode()); | |
| 228 | + })); | |
| 229 | + // 测试 status 不匹配 | |
| 230 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 231 | + o.setConfig(payClientConfig); | |
| 232 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | |
| 233 | + })); | |
| 234 | + // 测试 remark 不匹配 | |
| 235 | + channelMapper.insert(cloneIgnoreId(dbChannel, o ->{ | |
| 236 | + o.setConfig(payClientConfig); | |
| 237 | + o.setRemark("敏敏子的渠道"); | |
| 238 | + })); | |
| 239 | + // 测试 feeRate 不匹配 | |
| 240 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 241 | + o.setConfig(payClientConfig); | |
| 242 | + o.setFeeRate(1.23); | |
| 243 | + })); | |
| 244 | + // 测试 merchantId 不匹配 | |
| 245 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 246 | + o.setConfig(payClientConfig); | |
| 247 | + o.setMerchantId(2L); | |
| 248 | + })); | |
| 249 | + // 测试 appId 不匹配 | |
| 250 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 251 | + o.setConfig(payClientConfig); | |
| 252 | + o.setAppId(2L); | |
| 253 | + })); | |
| 254 | + // 测试 createTime 不匹配 | |
| 255 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 256 | + o.setConfig(payClientConfig); | |
| 257 | + o.setCreateTime(buildTime(2021, 10, 20)); | |
| 258 | + })); | |
| 259 | + // 准备参数 | |
| 260 | + PayChannelPageReqVO reqVO = new PayChannelPageReqVO(); | |
| 261 | + reqVO.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 262 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 263 | + reqVO.setRemark("灿灿子的支付渠道"); | |
| 264 | + reqVO.setFeeRate(0.03); | |
| 265 | + reqVO.setMerchantId(1L); | |
| 266 | + reqVO.setAppId(1L); | |
| 267 | + reqVO.setConfig(JSON.toJSONString(payClientConfig)); | |
| 268 | + reqVO.setBeginCreateTime(buildTime(2021,11,19)); | |
| 269 | + reqVO.setEndCreateTime(buildTime(2021,11,21)); | |
| 270 | + | |
| 271 | + // 调用 | |
| 272 | + PageResult<PayChannelDO> pageResult = channelService.getChannelPage(reqVO); | |
| 273 | + // 断言 | |
| 274 | + assertEquals(1, pageResult.getTotal()); | |
| 275 | + assertEquals(1, pageResult.getList().size()); | |
| 276 | + assertPojoEquals(dbChannel, pageResult.getList().get(0), "config"); | |
| 277 | + assertPojoEquals(payClientConfig, pageResult.getList().get(0).getConfig()); | |
| 278 | + | |
| 279 | + } | |
| 280 | + | |
| 281 | + @Test | |
| 282 | + public void testGetChannelList() { | |
| 283 | + // mock 数据 | |
| 284 | + AlipayPayClientConfig payClientConfig = getCertificateConfig(); | |
| 285 | + PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到 | |
| 286 | + o.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 287 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 288 | + o.setRemark("灿灿子的支付渠道"); | |
| 289 | + o.setFeeRate(0.03); | |
| 290 | + o.setMerchantId(1L); | |
| 291 | + o.setAppId(1L); | |
| 292 | + o.setConfig(payClientConfig); | |
| 293 | + o.setCreateTime(buildTime(2021,11,20)); | |
| 294 | + }); | |
| 295 | + channelMapper.insert(dbChannel); | |
| 296 | + // 执行拷贝的时候会出现异常,所以在插入后要重置为null 后续在写入新的 | |
| 297 | + dbChannel.setConfig(null); | |
| 298 | + // 测试 code 不匹配 | |
| 299 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 300 | + o.setConfig(payClientConfig); | |
| 301 | + o.setCode(PayChannelEnum.WX_PUB.getCode()); | |
| 302 | + })); | |
| 303 | + // 测试 status 不匹配 | |
| 304 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 305 | + o.setConfig(payClientConfig); | |
| 306 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | |
| 307 | + })); | |
| 308 | + // 测试 remark 不匹配 | |
| 309 | + channelMapper.insert(cloneIgnoreId(dbChannel, o ->{ | |
| 310 | + o.setConfig(payClientConfig); | |
| 311 | + o.setRemark("敏敏子的渠道"); | |
| 312 | + })); | |
| 313 | + // 测试 feeRate 不匹配 | |
| 314 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 315 | + o.setConfig(payClientConfig); | |
| 316 | + o.setFeeRate(1.23); | |
| 317 | + })); | |
| 318 | + // 测试 merchantId 不匹配 | |
| 319 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 320 | + o.setConfig(payClientConfig); | |
| 321 | + o.setMerchantId(2L); | |
| 322 | + })); | |
| 323 | + // 测试 appId 不匹配 | |
| 324 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 325 | + o.setConfig(payClientConfig); | |
| 326 | + o.setAppId(2L); | |
| 327 | + })); | |
| 328 | + // 测试 createTime 不匹配 | |
| 329 | + channelMapper.insert(cloneIgnoreId(dbChannel, o -> { | |
| 330 | + o.setConfig(payClientConfig); | |
| 331 | + o.setCreateTime(buildTime(2021, 10, 20)); | |
| 332 | + })); | |
| 333 | + // 准备参数 | |
| 334 | + PayChannelExportReqVO reqVO = new PayChannelExportReqVO(); | |
| 335 | + reqVO.setCode(PayChannelEnum.ALIPAY_APP.getCode()); | |
| 336 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 337 | + reqVO.setRemark("灿灿子的支付渠道"); | |
| 338 | + reqVO.setFeeRate(0.03); | |
| 339 | + reqVO.setMerchantId(1L); | |
| 340 | + reqVO.setAppId(1L); | |
| 341 | + reqVO.setConfig(JSON.toJSONString(payClientConfig)); | |
| 342 | + reqVO.setBeginCreateTime(buildTime(2021,11,19)); | |
| 343 | + reqVO.setEndCreateTime(buildTime(2021,11,21)); | |
| 344 | + | |
| 345 | + // 调用 | |
| 346 | + List<PayChannelDO> list = channelService.getChannelList(reqVO); | |
| 347 | + // 断言 | |
| 348 | + assertEquals(1, list.size()); | |
| 349 | + assertPojoEquals(dbChannel, list.get(0), "config"); | |
| 350 | + assertPojoEquals(payClientConfig, list.get(0).getConfig()); | |
| 351 | + } | |
| 352 | + | |
| 353 | + | |
| 354 | + public WXPayClientConfig getV2Config() { | |
| 355 | + return new WXPayClientConfig() | |
| 356 | + .setAppId("APP00001") | |
| 357 | + .setMchId("MCH00001") | |
| 358 | + .setApiVersion(WXPayClientConfig.API_VERSION_V2) | |
| 359 | + .setMchKey("dsa1d5s6a1d6sa16d1sa56d15a61das6") | |
| 360 | + .setApiV3Key("") | |
| 361 | + .setPrivateCertContent("") | |
| 362 | + .setPrivateKeyContent(""); | |
| 363 | + } | |
| 364 | + | |
| 365 | + public WXPayClientConfig getV3Config() { | |
| 366 | + return new WXPayClientConfig() | |
| 367 | + .setAppId("APP00001") | |
| 368 | + .setMchId("MCH00001") | |
| 369 | + .setApiVersion(WXPayClientConfig.API_VERSION_V3) | |
| 370 | + .setMchKey("") | |
| 371 | + .setApiV3Key("sdadasdsadadsa") | |
| 372 | + .setPrivateKeyContent("dsa445das415d15asd16ad156as") | |
| 373 | + .setPrivateCertContent("dsadasd45asd4s5a"); | |
| 374 | + | |
| 375 | + } | |
| 376 | + | |
| 377 | + public AlipayPayClientConfig getPublicKeyConfig() { | |
| 378 | + return new AlipayPayClientConfig() | |
| 379 | + .setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD) | |
| 380 | + .setAppId("APP00001") | |
| 381 | + .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT) | |
| 382 | + .setMode(AlipayPayClientConfig.MODE_PUBLIC_KEY) | |
| 383 | + .setPrivateKey("13131321312") | |
| 384 | + .setAlipayPublicKey("13321321321") | |
| 385 | + .setAppCertContent("") | |
| 386 | + .setAlipayPublicCertContent("") | |
| 387 | + .setRootCertContent(""); | |
| 388 | + } | |
| 389 | + | |
| 390 | + public AlipayPayClientConfig getCertificateConfig() { | |
| 391 | + return new AlipayPayClientConfig() | |
| 392 | + .setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD) | |
| 393 | + .setAppId("APP00001") | |
| 394 | + .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT) | |
| 395 | + .setMode(AlipayPayClientConfig.MODE_CERTIFICATE) | |
| 396 | + .setPrivateKey("") | |
| 397 | + .setAlipayPublicKey("") | |
| 398 | + .setAppCertContent("13321321321sda") | |
| 399 | + .setAlipayPublicCertContent("13321321321aqeqw") | |
| 400 | + .setRootCertContent("13321321321dsad"); | |
| 401 | + } | |
| 402 | + | |
| 403 | + | |
| 404 | +} | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.merchant; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.RandomUtil; | |
| 4 | +import cn.iocoder.yudao.adminserver.BaseDbUnitTest; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; | |
| 10 | +import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl.PayMerchantServiceImpl; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | |
| 12 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import org.junit.jupiter.api.Test; | |
| 15 | +import org.springframework.context.annotation.Import; | |
| 16 | + | |
| 17 | +import javax.annotation.Resource; | |
| 18 | +import java.util.List; | |
| 19 | + | |
| 20 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; | |
| 22 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | |
| 24 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 25 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | |
| 26 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 27 | +import static org.junit.jupiter.api.Assertions.*; | |
| 28 | + | |
| 29 | +/** | |
| 30 | +* {@link PayMerchantServiceImpl} 的单元测试类 | |
| 31 | +* | |
| 32 | +* @author aquan | |
| 33 | +*/ | |
| 34 | +@Import(PayMerchantServiceImpl.class) | |
| 35 | +public class PayMerchantServiceTest extends BaseDbUnitTest { | |
| 36 | + | |
| 37 | + @Resource | |
| 38 | + private PayMerchantServiceImpl merchantService; | |
| 39 | + | |
| 40 | + @Resource | |
| 41 | + private PayMerchantMapper merchantMapper; | |
| 42 | + | |
| 43 | + @Test | |
| 44 | + public void testCreateMerchant_success() { | |
| 45 | + // 准备参数 | |
| 46 | + PayMerchantCreateReqVO reqVO = randomPojo(PayMerchantCreateReqVO.class,o -> | |
| 47 | + o.setStatus(RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())); | |
| 48 | + | |
| 49 | + // 调用 | |
| 50 | + Long merchantId = merchantService.createMerchant(reqVO); | |
| 51 | + // 断言 | |
| 52 | + assertNotNull(merchantId); | |
| 53 | + // 校验记录的属性是否正确 | |
| 54 | + PayMerchantDO merchant = merchantMapper.selectById(merchantId); | |
| 55 | + assertPojoEquals(reqVO, merchant); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Test | |
| 59 | + public void testUpdateMerchant_success() { | |
| 60 | + // mock 数据 | |
| 61 | + PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> | |
| 62 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus())); | |
| 63 | + merchantMapper.insert(dbMerchant);// @Sql: 先插入出一条存在的数据 | |
| 64 | + // 准备参数 | |
| 65 | + PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class, o -> { | |
| 66 | + o.setId(dbMerchant.getId()); // 设置更新的 ID | |
| 67 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | |
| 68 | + }); | |
| 69 | + | |
| 70 | + // 调用 | |
| 71 | + merchantService.updateMerchant(reqVO); | |
| 72 | + // 校验是否更新正确 | |
| 73 | + PayMerchantDO merchant = merchantMapper.selectById(reqVO.getId()); // 获取最新的 | |
| 74 | + assertPojoEquals(reqVO, merchant); | |
| 75 | + } | |
| 76 | + | |
| 77 | + @Test | |
| 78 | + public void testUpdateMerchant_notExists() { | |
| 79 | + // 准备参数 | |
| 80 | + PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class); | |
| 81 | + | |
| 82 | + // 调用, 并断言异常 | |
| 83 | + assertServiceException(() -> merchantService.updateMerchant(reqVO), PAY_MERCHANT_NOT_EXISTS); | |
| 84 | + } | |
| 85 | + | |
| 86 | + @Test | |
| 87 | + public void testDeleteMerchant_success() { | |
| 88 | + // mock 数据 | |
| 89 | + PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, | |
| 90 | + o-> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); | |
| 91 | + merchantMapper.insert(dbMerchant);// @Sql: 先插入出一条存在的数据 | |
| 92 | + // 准备参数 | |
| 93 | + Long id = dbMerchant.getId(); | |
| 94 | + | |
| 95 | + // 调用 | |
| 96 | + merchantService.deleteMerchant(id); | |
| 97 | + // 校验数据不存在了 | |
| 98 | + assertNull(merchantMapper.selectById(id)); | |
| 99 | + } | |
| 100 | + | |
| 101 | + @Test | |
| 102 | + public void testDeleteMerchant_notExists() { | |
| 103 | + // 准备参数 | |
| 104 | + Long id = randomLongId(); | |
| 105 | + | |
| 106 | + // 调用, 并断言异常 | |
| 107 | + assertServiceException(() -> merchantService.deleteMerchant(id), PAY_MERCHANT_NOT_EXISTS); | |
| 108 | + } | |
| 109 | + | |
| 110 | + @Test | |
| 111 | + public void testGetMerchantPage() { | |
| 112 | + // mock 数据 | |
| 113 | + PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到 | |
| 114 | + o.setNo("M1008611"); | |
| 115 | + o.setName("灿哥的杂货铺"); | |
| 116 | + o.setShortName("灿灿子"); | |
| 117 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 118 | + o.setRemark("灿哥的杂货铺"); | |
| 119 | + o.setCreateTime(buildTime(2021,11,3)); | |
| 120 | + }); | |
| 121 | + merchantMapper.insert(dbMerchant); | |
| 122 | + // 测试 no 不匹配 | |
| 123 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setNo("M200000"))); | |
| 124 | + // 测试 name 不匹配 | |
| 125 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setName("斌哥的杂货铺"))); | |
| 126 | + // 测试 shortName 不匹配 | |
| 127 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setShortName("斌斌子"))); | |
| 128 | + // 测试 status 不匹配 | |
| 129 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); | |
| 130 | + // 测试 remark 不匹配 | |
| 131 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setRemark("斌哥的杂货铺"))); | |
| 132 | + // 测试 createTime 不匹配 | |
| 133 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildTime(2022,12,4)))); | |
| 134 | + // 准备参数 | |
| 135 | + PayMerchantPageReqVO reqVO = new PayMerchantPageReqVO(); | |
| 136 | + reqVO.setNo("M1008611"); | |
| 137 | + reqVO.setName("灿哥的杂货铺"); | |
| 138 | + reqVO.setShortName("灿灿子"); | |
| 139 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 140 | + reqVO.setRemark("灿哥的杂货铺"); | |
| 141 | + reqVO.setBeginCreateTime(buildTime(2021,11,2)); | |
| 142 | + reqVO.setEndCreateTime(buildTime(2021,11,4)); | |
| 143 | + | |
| 144 | + // 调用 | |
| 145 | + PageResult<PayMerchantDO> pageResult = merchantService.getMerchantPage(reqVO); | |
| 146 | + // 断言 | |
| 147 | + assertEquals(1, pageResult.getTotal()); | |
| 148 | + assertEquals(1, pageResult.getList().size()); | |
| 149 | + assertPojoEquals(dbMerchant, pageResult.getList().get(0)); | |
| 150 | + } | |
| 151 | + | |
| 152 | + @Test | |
| 153 | + public void testGetMerchantList() { | |
| 154 | + // mock 数据 | |
| 155 | + PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到 | |
| 156 | + o.setNo("M1008611"); | |
| 157 | + o.setName("灿哥的杂货铺"); | |
| 158 | + o.setShortName("灿灿子"); | |
| 159 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 160 | + o.setRemark("灿哥的杂货铺"); | |
| 161 | + o.setCreateTime(buildTime(2021,11,3)); | |
| 162 | + }); | |
| 163 | + merchantMapper.insert(dbMerchant); | |
| 164 | + // 测试 no 不匹配 | |
| 165 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setNo("M200000"))); | |
| 166 | + // 测试 name 不匹配 | |
| 167 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setName("斌哥的杂货铺"))); | |
| 168 | + // 测试 shortName 不匹配 | |
| 169 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setShortName("斌斌子"))); | |
| 170 | + // 测试 status 不匹配 | |
| 171 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); | |
| 172 | + // 测试 remark 不匹配 | |
| 173 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setRemark("斌哥的杂货铺"))); | |
| 174 | + // 测试 createTime 不匹配 | |
| 175 | + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildTime(2022,12,4)))); | |
| 176 | + // 准备参数 | |
| 177 | + PayMerchantExportReqVO reqVO = new PayMerchantExportReqVO(); | |
| 178 | + reqVO.setNo("M1008611"); | |
| 179 | + reqVO.setName("灿哥的杂货铺"); | |
| 180 | + reqVO.setShortName("灿灿子"); | |
| 181 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 182 | + reqVO.setRemark("灿哥的杂货铺"); | |
| 183 | + reqVO.setBeginCreateTime(buildTime(2021,11,2)); | |
| 184 | + reqVO.setEndCreateTime(buildTime(2021,11,4)); | |
| 185 | + | |
| 186 | + // 调用 | |
| 187 | + List<PayMerchantDO> list = merchantService.getMerchantList(reqVO); | |
| 188 | + // 断言 | |
| 189 | + assertEquals(1, list.size()); | |
| 190 | + assertPojoEquals(dbMerchant, list.get(0)); | |
| 191 | + } | |
| 192 | + | |
| 193 | +} | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderServiceTest.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.order; | |
| 2 | + | |
| 3 | +import cn.hutool.core.date.DateUtil; | |
| 4 | +import cn.hutool.core.util.RandomUtil; | |
| 5 | +import cn.iocoder.yudao.adminserver.BaseDbUnitTest; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; | |
| 8 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper; | |
| 9 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.impl.PayOrderServiceImpl; | |
| 10 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; | |
| 12 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; | |
| 13 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 15 | +import cn.iocoder.yudao.framework.common.util.date.DateUtils; | |
| 16 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 17 | +import org.junit.jupiter.api.Test; | |
| 18 | +import org.springframework.context.annotation.Import; | |
| 19 | + | |
| 20 | +import javax.annotation.Resource; | |
| 21 | +import java.util.Date; | |
| 22 | +import java.util.List; | |
| 23 | + | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 25 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | |
| 26 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 27 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * {@link PayOrderServiceImpl} 的单元测试类 | |
| 31 | + * | |
| 32 | + * @author 芋艿 | |
| 33 | + */ | |
| 34 | +@Import(PayOrderServiceImpl.class) | |
| 35 | +public class PayOrderServiceTest extends BaseDbUnitTest { | |
| 36 | + | |
| 37 | + @Resource | |
| 38 | + private PayOrderServiceImpl orderService; | |
| 39 | + | |
| 40 | + @Resource | |
| 41 | + private PayOrderMapper orderMapper; | |
| 42 | + | |
| 43 | + public String generateNo() { | |
| 44 | + return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); | |
| 45 | + } | |
| 46 | + | |
| 47 | + @Test | |
| 48 | + public void testGetOrderPage() { | |
| 49 | + | |
| 50 | + String merchantOrderId = generateNo(); | |
| 51 | + String channelOrderId = generateNo(); | |
| 52 | + | |
| 53 | + // mock 数据 | |
| 54 | + PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 | |
| 55 | + o.setMerchantId(1L); | |
| 56 | + o.setAppId(1L); | |
| 57 | + o.setChannelId(1L); | |
| 58 | + o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 59 | + o.setMerchantOrderId(merchantOrderId); | |
| 60 | + o.setSubject("灿灿子的炸弹猫"); | |
| 61 | + o.setBody("斌斌子送给灿灿子的炸弹猫"); | |
| 62 | + o.setNotifyUrl("https://hc.com/lbh"); | |
| 63 | + o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 64 | + o.setAmount(10000L); | |
| 65 | + o.setChannelFeeRate(0.01); | |
| 66 | + o.setChannelFeeAmount(1L); | |
| 67 | + o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | |
| 68 | + o.setUserIp("127.0.0.1"); | |
| 69 | + o.setCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0)); | |
| 70 | + o.setExpireTime(DateUtils.buildTime(2018, 1, 1, 10, 30, 0)); | |
| 71 | + o.setSuccessTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 2)); | |
| 72 | + o.setNotifyTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15)); | |
| 73 | + o.setSuccessExtensionId(1L); | |
| 74 | + o.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); | |
| 75 | + o.setRefundTimes(0); | |
| 76 | + o.setRefundAmount(0L); | |
| 77 | + o.setChannelUserId("1008611"); | |
| 78 | + o.setChannelOrderNo(channelOrderId); | |
| 79 | + o.setUpdateTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15)); | |
| 80 | + }); | |
| 81 | + orderMapper.insert(dbOrder); | |
| 82 | + // 测试 merchantId 不匹配 | |
| 83 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantId(2L))); | |
| 84 | + // 测试 appId 不匹配 | |
| 85 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L))); | |
| 86 | + // 测试 channelId 不匹配 | |
| 87 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelId(2L))); | |
| 88 | + // 测试 channelCode 不匹配 | |
| 89 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | |
| 90 | + // 测试 merchantOrderId 不匹配 | |
| 91 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo()))); | |
| 92 | + // 测试 notifyStatus 不匹配 | |
| 93 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | |
| 94 | + // 测试 status 不匹配 | |
| 95 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); | |
| 96 | + // 测试 refundStatus 不匹配 | |
| 97 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus()))); | |
| 98 | + // 测试 createTime 不匹配 | |
| 99 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(DateUtils.buildTime(2019, 1, 1, 10, 10, | |
| 100 | + 1)))); | |
| 101 | + // 准备参数 | |
| 102 | + PayOrderPageReqVO reqVO = new PayOrderPageReqVO(); | |
| 103 | + reqVO.setMerchantId(1L); | |
| 104 | + reqVO.setAppId(1L); | |
| 105 | + reqVO.setChannelId(1L); | |
| 106 | + reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 107 | + reqVO.setMerchantOrderId(merchantOrderId); | |
| 108 | + reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 109 | + reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | |
| 110 | + reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); | |
| 111 | + reqVO.setBeginCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0)); | |
| 112 | + reqVO.setEndCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0)); | |
| 113 | + | |
| 114 | + // 调用 | |
| 115 | + PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO); | |
| 116 | + // 断言 | |
| 117 | + assertEquals(1, pageResult.getTotal()); | |
| 118 | + assertEquals(1, pageResult.getList().size()); | |
| 119 | + assertPojoEquals(dbOrder, pageResult.getList().get(0)); | |
| 120 | + // assertEquals(0, dbOrder.getUpdateTime().compareTo(pageResult.getList().get(0).getUpdateTime())); | |
| 121 | + } | |
| 122 | + | |
| 123 | + @Test | |
| 124 | + public void testGetOrderList() { | |
| 125 | + // mock 数据 | |
| 126 | + String merchantOrderId = generateNo(); | |
| 127 | + String channelOrderId = generateNo(); | |
| 128 | + PayOrderDO dbOrder = randomPojo(PayOrderDO.class, o -> { // 等会查询到 | |
| 129 | + o.setMerchantId(1L); | |
| 130 | + o.setAppId(1L); | |
| 131 | + o.setChannelId(1L); | |
| 132 | + o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 133 | + o.setMerchantOrderId(merchantOrderId); | |
| 134 | + o.setSubject("灿灿子的炸弹猫"); | |
| 135 | + o.setBody("斌斌子送给灿灿子的炸弹猫"); | |
| 136 | + o.setNotifyUrl("https://hc.com/lbh"); | |
| 137 | + o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 138 | + o.setAmount(10000L); | |
| 139 | + o.setChannelFeeRate(0.01); | |
| 140 | + o.setChannelFeeAmount(1L); | |
| 141 | + o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | |
| 142 | + o.setUserIp("127.0.0.1"); | |
| 143 | + o.setCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0)); | |
| 144 | + o.setExpireTime(DateUtils.buildTime(2018, 1, 1, 10, 30, 0)); | |
| 145 | + o.setSuccessTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 2)); | |
| 146 | + o.setNotifyTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15)); | |
| 147 | + o.setSuccessExtensionId(1L); | |
| 148 | + o.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); | |
| 149 | + o.setRefundTimes(0); | |
| 150 | + o.setRefundAmount(0L); | |
| 151 | + o.setChannelUserId("1008611"); | |
| 152 | + o.setChannelOrderNo(channelOrderId); | |
| 153 | + o.setUpdateTime(DateUtils.buildTime(2018, 1, 1, 10, 10, 15)); | |
| 154 | + | |
| 155 | + }); | |
| 156 | + orderMapper.insert(dbOrder); | |
| 157 | + // 测试 merchantId 不匹配 | |
| 158 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantId(2L))); | |
| 159 | + // 测试 appId 不匹配 | |
| 160 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setAppId(2L))); | |
| 161 | + // 测试 channelId 不匹配 | |
| 162 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelId(2L))); | |
| 163 | + // 测试 channelCode 不匹配 | |
| 164 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | |
| 165 | + // 测试 merchantOrderId 不匹配 | |
| 166 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setMerchantOrderId(generateNo()))); | |
| 167 | + // 测试 notifyStatus 不匹配 | |
| 168 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | |
| 169 | + // 测试 status 不匹配 | |
| 170 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()))); | |
| 171 | + // 测试 refundStatus 不匹配 | |
| 172 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus()))); | |
| 173 | + // 测试 createTime 不匹配 | |
| 174 | + orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(DateUtils.buildTime(2019, 1, 1, 10, 10, | |
| 175 | + 1)))); | |
| 176 | + // 准备参数 | |
| 177 | + PayOrderExportReqVO reqVO = new PayOrderExportReqVO(); | |
| 178 | + reqVO.setMerchantId(1L); | |
| 179 | + reqVO.setAppId(1L); | |
| 180 | + reqVO.setChannelId(1L); | |
| 181 | + reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 182 | + reqVO.setMerchantOrderId(merchantOrderId); | |
| 183 | + reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 184 | + reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); | |
| 185 | + reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus()); | |
| 186 | + reqVO.setBeginCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0)); | |
| 187 | + reqVO.setEndCreateTime(DateUtils.buildTime(2018, 1, 1, 10, 1, 0)); | |
| 188 | + | |
| 189 | + // 调用 | |
| 190 | + List<PayOrderDO> list = orderService.getOrderList(reqVO); | |
| 191 | + // 断言 | |
| 192 | + assertEquals(1, list.size()); | |
| 193 | + assertPojoEquals(dbOrder, list.get(0)); | |
| 194 | + } | |
| 195 | + | |
| 196 | +} | ... | ... |
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/refund/PayRefundServiceTest.java
0 → 100755
| 1 | +package cn.iocoder.yudao.adminserver.modules.pay.service.refund; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.adminserver.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.pay.service.order.impl.PayRefundServiceImpl; | |
| 8 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 9 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; | |
| 10 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 12 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 13 | +import cn.iocoder.yudao.framework.common.util.date.DateUtils; | |
| 14 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 15 | +import org.junit.jupiter.api.Test; | |
| 16 | +import org.springframework.context.annotation.Import; | |
| 17 | + | |
| 18 | +import javax.annotation.Resource; | |
| 19 | +import java.util.List; | |
| 20 | + | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 24 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 25 | + | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * {@link PayRefundServiceImpl} 的单元测试类 | |
| 29 | + * | |
| 30 | + * @author aquan | |
| 31 | + */ | |
| 32 | +@Import(PayRefundServiceImpl.class) | |
| 33 | +public class PayRefundServiceTest extends BaseDbUnitTest { | |
| 34 | + | |
| 35 | + @Resource | |
| 36 | + private PayRefundServiceImpl refundService; | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private PayRefundMapper refundMapper; | |
| 40 | + | |
| 41 | + | |
| 42 | + @Test | |
| 43 | + public void testGetRefundPage() { | |
| 44 | + // mock 数据 | |
| 45 | + PayRefundDO dbRefund = randomPojo(PayRefundDO.class, o -> { // 等会查询到 | |
| 46 | + o.setMerchantId(1L); | |
| 47 | + o.setAppId(1L); | |
| 48 | + o.setChannelId(1L); | |
| 49 | + o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 50 | + o.setOrderId(1L); | |
| 51 | + o.setTradeNo("OT0000001"); | |
| 52 | + o.setMerchantOrderId("MOT0000001"); | |
| 53 | + o.setMerchantRefundNo("MRF0000001"); | |
| 54 | + o.setNotifyUrl("https://www.cancanzi.com"); | |
| 55 | + o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 56 | + o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | |
| 57 | + o.setType(PayRefundTypeEnum.SOME.getStatus()); | |
| 58 | + o.setPayAmount(100L); | |
| 59 | + o.setRefundAmount(500L); | |
| 60 | + o.setReason("就是想退款了,你有意见吗"); | |
| 61 | + o.setUserIp("127.0.0.1"); | |
| 62 | + o.setChannelOrderNo("CH0000001"); | |
| 63 | + o.setChannelRefundNo("CHR0000001"); | |
| 64 | + o.setChannelErrorCode(""); | |
| 65 | + o.setChannelErrorMsg(""); | |
| 66 | + o.setChannelExtras(""); | |
| 67 | + o.setExpireTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 30)); | |
| 68 | + o.setSuccessTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 15)); | |
| 69 | + o.setNotifyTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 20)); | |
| 70 | + o.setCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10)); | |
| 71 | + o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35)); | |
| 72 | + }); | |
| 73 | + refundMapper.insert(dbRefund); | |
| 74 | + // 测试 merchantId 不匹配 | |
| 75 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L))); | |
| 76 | + // 测试 appId 不匹配 | |
| 77 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setAppId(2L))); | |
| 78 | + // 测试 channelCode 不匹配 | |
| 79 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | |
| 80 | + // 测试 merchantRefundNo 不匹配 | |
| 81 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112"))); | |
| 82 | + // 测试 notifyStatus 不匹配 | |
| 83 | + refundMapper.insert( | |
| 84 | + cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | |
| 85 | + // 测试 status 不匹配 | |
| 86 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus()))); | |
| 87 | + // 测试 type 不匹配 | |
| 88 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus()))); | |
| 89 | + // 测试 createTime 不匹配 | |
| 90 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> | |
| 91 | + o.setCreateTime(DateUtils.buildTime(2022, 1, 1, 10, 10, 10)))); | |
| 92 | + // 准备参数 | |
| 93 | + PayRefundPageReqVO reqVO = new PayRefundPageReqVO(); | |
| 94 | + reqVO.setMerchantId(1L); | |
| 95 | + reqVO.setAppId(1L); | |
| 96 | + reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 97 | + reqVO.setMerchantRefundNo("MRF0000001"); | |
| 98 | + reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 99 | + reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | |
| 100 | + reqVO.setType(PayRefundTypeEnum.SOME.getStatus()); | |
| 101 | + reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10)); | |
| 102 | + reqVO.setEndCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 12)); | |
| 103 | + | |
| 104 | + | |
| 105 | + // 调用 | |
| 106 | + PageResult<PayRefundDO> pageResult = refundService.getRefundPage(reqVO); | |
| 107 | + // 断言 | |
| 108 | + assertEquals(1, pageResult.getTotal()); | |
| 109 | + assertEquals(1, pageResult.getList().size()); | |
| 110 | + assertPojoEquals(dbRefund, pageResult.getList().get(0)); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @Test | |
| 114 | + public void testGetRefundList() { | |
| 115 | + // mock 数据 | |
| 116 | + PayRefundDO dbRefund = randomPojo(PayRefundDO.class, o -> { // 等会查询到 | |
| 117 | + o.setMerchantId(1L); | |
| 118 | + o.setAppId(1L); | |
| 119 | + o.setChannelId(1L); | |
| 120 | + o.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 121 | + o.setOrderId(1L); | |
| 122 | + o.setTradeNo("OT0000001"); | |
| 123 | + o.setMerchantOrderId("MOT0000001"); | |
| 124 | + o.setMerchantRefundNo("MRF0000001"); | |
| 125 | + o.setNotifyUrl("https://www.cancanzi.com"); | |
| 126 | + o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 127 | + o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | |
| 128 | + o.setType(PayRefundTypeEnum.SOME.getStatus()); | |
| 129 | + o.setPayAmount(100L); | |
| 130 | + o.setRefundAmount(500L); | |
| 131 | + o.setReason("就是想退款了,你有意见吗"); | |
| 132 | + o.setUserIp("127.0.0.1"); | |
| 133 | + o.setChannelOrderNo("CH0000001"); | |
| 134 | + o.setChannelRefundNo("CHR0000001"); | |
| 135 | + o.setChannelErrorCode(""); | |
| 136 | + o.setChannelErrorMsg(""); | |
| 137 | + o.setChannelExtras(""); | |
| 138 | + o.setExpireTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 30)); | |
| 139 | + o.setSuccessTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 15)); | |
| 140 | + o.setNotifyTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 20)); | |
| 141 | + o.setCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10)); | |
| 142 | + o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35)); | |
| 143 | + }); | |
| 144 | + refundMapper.insert(dbRefund); | |
| 145 | + // 测试 merchantId 不匹配 | |
| 146 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L))); | |
| 147 | + // 测试 appId 不匹配 | |
| 148 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setAppId(2L))); | |
| 149 | + // 测试 channelCode 不匹配 | |
| 150 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode()))); | |
| 151 | + // 测试 merchantRefundNo 不匹配 | |
| 152 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112"))); | |
| 153 | + // 测试 notifyStatus 不匹配 | |
| 154 | + refundMapper.insert( | |
| 155 | + cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus()))); | |
| 156 | + // 测试 status 不匹配 | |
| 157 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus()))); | |
| 158 | + // 测试 type 不匹配 | |
| 159 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus()))); | |
| 160 | + // 测试 createTime 不匹配 | |
| 161 | + refundMapper.insert(cloneIgnoreId(dbRefund, o -> | |
| 162 | + o.setCreateTime(DateUtils.buildTime(2022, 1, 1, 10, 10, 10)))); | |
| 163 | + | |
| 164 | + // 准备参数 | |
| 165 | + PayRefundExportReqVO reqVO = new PayRefundExportReqVO(); | |
| 166 | + reqVO.setMerchantId(1L); | |
| 167 | + reqVO.setAppId(1L); | |
| 168 | + reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); | |
| 169 | + reqVO.setMerchantRefundNo("MRF0000001"); | |
| 170 | + reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); | |
| 171 | + reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | |
| 172 | + reqVO.setType(PayRefundTypeEnum.SOME.getStatus()); | |
| 173 | + reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 10)); | |
| 174 | + reqVO.setEndCreateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 12)); | |
| 175 | + | |
| 176 | + // 调用 | |
| 177 | + List<PayRefundDO> list = refundService.getRefundList(reqVO); | |
| 178 | + // 断言 | |
| 179 | + assertEquals(1, list.size()); | |
| 180 | + assertPojoEquals(dbRefund, list.get(0)); | |
| 181 | + } | |
| 182 | + | |
| 183 | +} | ... | ... |
yudao-admin-server/src/test/resources/sql/clean.sql
| ... | ... | @@ -26,5 +26,12 @@ DELETE FROM "sys_error_code"; |
| 26 | 26 | DELETE FROM "sys_social_user"; |
| 27 | 27 | DELETE FROM "sys_tenant"; |
| 28 | 28 | |
| 29 | +-- pay 开头的 DB | |
| 30 | +DELETE FROM pay_merchant; | |
| 31 | +DELETE FROM pay_app; | |
| 32 | +DELETE FROM pay_channel; | |
| 33 | +DELETE FROM pay_order; | |
| 34 | +DELETE FROM pay_refund; | |
| 35 | + | |
| 29 | 36 | -- bpm 开头的 DB |
| 30 | 37 | DELETE FROM "bpm_form"; | ... | ... |
yudao-admin-server/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -474,6 +474,131 @@ CREATE TABLE IF NOT EXISTS "sys_tenant" ( |
| 474 | 474 | ) COMMENT '租户'; |
| 475 | 475 | |
| 476 | 476 | |
| 477 | +CREATE TABLE IF NOT EXISTS "pay_merchant" | |
| 478 | +( | |
| 479 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 480 | + "no" varchar(32) NOT NULL, | |
| 481 | + "name" varchar(64) NOT NULL, | |
| 482 | + "short_name" varchar(64) NOT NULL, | |
| 483 | + "status" tinyint NOT NULL, | |
| 484 | + "remark" varchar(255) DEFAULT NULL, | |
| 485 | + "creator" varchar(64) DEFAULT '', | |
| 486 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 487 | + "updater" varchar(64) DEFAULT '', | |
| 488 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
| 489 | + "deleted" bit(1) NOT NULL DEFAULT FALSE, | |
| 490 | + PRIMARY KEY ("id") | |
| 491 | +) COMMENT '支付商户信息'; | |
| 492 | + | |
| 493 | +CREATE TABLE IF NOT EXISTS "pay_app" | |
| 494 | +( | |
| 495 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 496 | + "name" varchar(64) NOT NULL, | |
| 497 | + "status" tinyint NOT NULL, | |
| 498 | + "remark" varchar(255) DEFAULT NULL, | |
| 499 | + `pay_notify_url` varchar(1024) NOT NULL, | |
| 500 | + `refund_notify_url` varchar(1024) NOT NULL, | |
| 501 | + `merchant_id` bigint(20) NOT NULL, | |
| 502 | + "creator" varchar(64) DEFAULT '', | |
| 503 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 504 | + "updater" varchar(64) DEFAULT '', | |
| 505 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
| 506 | + "deleted" bit(1) NOT NULL DEFAULT FALSE, | |
| 507 | + PRIMARY KEY ("id") | |
| 508 | +) COMMENT = '支付应用信息'; | |
| 509 | + | |
| 510 | +CREATE TABLE IF NOT EXISTS "pay_channel" | |
| 511 | +( | |
| 512 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 513 | + "code" varchar(32) NOT NULL, | |
| 514 | + "status" tinyint(4) NOT NULL, | |
| 515 | + "remark" varchar(255) DEFAULT NULL, | |
| 516 | + "fee_rate" double NOT NULL DEFAULT 0, | |
| 517 | + "merchant_id" bigint(20) NOT NULL, | |
| 518 | + "app_id" bigint(20) NOT NULL, | |
| 519 | + "config" varchar(10240) NOT NULL, | |
| 520 | + "creator" varchar(64) NULL DEFAULT '', | |
| 521 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 522 | + "updater" varchar(64) NULL DEFAULT '', | |
| 523 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
| 524 | + "deleted" bit(1) NOT NULL DEFAULT FALSE, | |
| 525 | + PRIMARY KEY ("id") | |
| 526 | +) COMMENT = '支付渠道'; | |
| 527 | + | |
| 528 | +CREATE TABLE IF NOT EXISTS `pay_order` | |
| 529 | +( | |
| 530 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 531 | + `merchant_id` bigint(20) NOT NULL, | |
| 532 | + `app_id` bigint(20) NOT NULL, | |
| 533 | + `channel_id` bigint(20) DEFAULT NULL, | |
| 534 | + `channel_code` varchar(32) DEFAULT NULL, | |
| 535 | + `merchant_order_id` varchar(64) NOT NULL, | |
| 536 | + `subject` varchar(32) NOT NULL, | |
| 537 | + `body` varchar(128) NOT NULL, | |
| 538 | + `notify_url` varchar(1024) NOT NULL, | |
| 539 | + `notify_status` tinyint(4) NOT NULL, | |
| 540 | + `amount` bigint(20) NOT NULL, | |
| 541 | + `channel_fee_rate` double DEFAULT 0, | |
| 542 | + `channel_fee_amount` bigint(20) DEFAULT 0, | |
| 543 | + `status` tinyint(4) NOT NULL, | |
| 544 | + `user_ip` varchar(50) NOT NULL, | |
| 545 | + `expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 546 | + `success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, | |
| 547 | + `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, | |
| 548 | + `success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号', | |
| 549 | + `refund_status` tinyint(4) NOT NULL, | |
| 550 | + `refund_times` tinyint(4) NOT NULL, | |
| 551 | + `refund_amount` bigint(20) NOT NULL, | |
| 552 | + `channel_user_id` varchar(255) DEFAULT NULL, | |
| 553 | + `channel_order_no` varchar(64) DEFAULT NULL, | |
| 554 | + `creator` varchar(64) DEFAULT '', | |
| 555 | + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 556 | + `updater` varchar(64) DEFAULT '', | |
| 557 | + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
| 558 | + `deleted` bit(1) NOT NULL DEFAULT FALSE, | |
| 559 | + PRIMARY KEY ("id") | |
| 560 | +) COMMENT = '支付订单'; | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | +CREATE TABLE IF NOT EXISTS `pay_refund` | |
| 565 | +( | |
| 566 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 567 | + `req_no` varchar(64) NOT NULL, | |
| 568 | + `merchant_id` bigint(20) NOT NULL, | |
| 569 | + `app_id` bigint(20) NOT NULL, | |
| 570 | + `channel_id` bigint(20) NOT NULL, | |
| 571 | + `channel_code` varchar(32) NOT NULL, | |
| 572 | + `order_id` bigint(20) NOT NULL, | |
| 573 | + `trade_no` varchar(64) NOT NULL, | |
| 574 | + `merchant_order_id` varchar(64) NOT NULL, | |
| 575 | + `merchant_refund_no` varchar(64) NOT NULL, | |
| 576 | + `notify_url` varchar(1024) NOT NULL, | |
| 577 | + `notify_status` tinyint(4) NOT NULL, | |
| 578 | + `status` tinyint(4) NOT NULL, | |
| 579 | + `type` tinyint(4) NOT NULL, | |
| 580 | + `pay_amount` bigint(20) NOT NULL, | |
| 581 | + `refund_amount` bigint(20) NOT NULL, | |
| 582 | + `reason` varchar(256) NOT NULL, | |
| 583 | + `user_ip` varchar(50) NULL DEFAULT NULL, | |
| 584 | + `channel_order_no` varchar(64) NOT NULL, | |
| 585 | + `channel_refund_no` varchar(64) NULL DEFAULT NULL, | |
| 586 | + `channel_error_code` varchar(128) NULL DEFAULT NULL, | |
| 587 | + `channel_error_msg` varchar(256) NULL DEFAULT NULL, | |
| 588 | + `channel_extras` varchar(1024) NULL DEFAULT NULL, | |
| 589 | + `expire_time` datetime(0) NULL DEFAULT NULL, | |
| 590 | + `success_time` datetime(0) NULL DEFAULT NULL, | |
| 591 | + `notify_time` datetime(0) NULL DEFAULT NULL, | |
| 592 | + `creator` varchar(64) NULL DEFAULT '', | |
| 593 | + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 594 | + `updater` varchar(64) NULL DEFAULT '', | |
| 595 | + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
| 596 | + `deleted` bit(1) NOT NULL DEFAULT FALSE, | |
| 597 | + PRIMARY KEY ("id") | |
| 598 | +) COMMENT = '退款订单'; | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 477 | 602 | CREATE TABLE IF NOT EXISTS "bpm_form" ( |
| 478 | 603 | "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, |
| 479 | 604 | "name" varchar(63) NOT NULL, | ... | ... |
yudao-admin-ui/package.json
yudao-admin-ui/src/api/pay/app.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 创建支付应用信息 | |
| 4 | +export function createApp(data) { | |
| 5 | + return request({ | |
| 6 | + url: '/pay/app/create', | |
| 7 | + method: 'post', | |
| 8 | + data: data | |
| 9 | + }) | |
| 10 | +} | |
| 11 | + | |
| 12 | +// 更新支付应用信息 | |
| 13 | +export function updateApp(data) { | |
| 14 | + return request({ | |
| 15 | + url: '/pay/app/update', | |
| 16 | + method: 'put', | |
| 17 | + data: data | |
| 18 | + }) | |
| 19 | +} | |
| 20 | + | |
| 21 | +// 支付应用信息状态修改 | |
| 22 | +export function changeAppStatus(id, status) { | |
| 23 | + const data = { | |
| 24 | + id, | |
| 25 | + status | |
| 26 | + } | |
| 27 | + return request({ | |
| 28 | + url: '/pay/app/update-status', | |
| 29 | + method: 'put', | |
| 30 | + data: data | |
| 31 | + }) | |
| 32 | +} | |
| 33 | + | |
| 34 | +// 删除支付应用信息 | |
| 35 | +export function deleteApp(id) { | |
| 36 | + return request({ | |
| 37 | + url: '/pay/app/delete?id=' + id, | |
| 38 | + method: 'delete' | |
| 39 | + }) | |
| 40 | +} | |
| 41 | + | |
| 42 | +// 获得支付应用信息 | |
| 43 | +export function getApp(id) { | |
| 44 | + return request({ | |
| 45 | + url: '/pay/app/get?id=' + id, | |
| 46 | + method: 'get' | |
| 47 | + }) | |
| 48 | +} | |
| 49 | + | |
| 50 | +// 获得支付应用信息分页 | |
| 51 | +export function getAppPage(query) { | |
| 52 | + return request({ | |
| 53 | + url: '/pay/app/page', | |
| 54 | + method: 'get', | |
| 55 | + params: query | |
| 56 | + }) | |
| 57 | +} | |
| 58 | + | |
| 59 | +// 导出支付应用信息 Excel | |
| 60 | +export function exportAppExcel(query) { | |
| 61 | + return request({ | |
| 62 | + url: '/pay/app/export-excel', | |
| 63 | + method: 'get', | |
| 64 | + params: query, | |
| 65 | + responseType: 'blob' | |
| 66 | + }) | |
| 67 | +} | |
| 68 | + | |
| 69 | +// 根据商ID称搜索应用列表 | |
| 70 | +export function getAppListByMerchantId(merchantId) { | |
| 71 | + return request({ | |
| 72 | + url: '/pay/app/list-merchant-id', | |
| 73 | + params:{ | |
| 74 | + merchantId:merchantId | |
| 75 | + }, | |
| 76 | + method: 'get' | |
| 77 | + }) | |
| 78 | +} | ... | ... |
yudao-admin-ui/src/api/pay/channel.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 创建支付渠道 | |
| 4 | +export function createChannel(data) { | |
| 5 | + return request({ | |
| 6 | + url: '/pay/channel/create', | |
| 7 | + method: 'post', | |
| 8 | + data: data | |
| 9 | + }) | |
| 10 | +} | |
| 11 | + | |
| 12 | + | |
| 13 | +// 更新支付渠道 | |
| 14 | +export function updateChannel(data) { | |
| 15 | + return request({ | |
| 16 | + url: '/pay/channel/update', | |
| 17 | + method: 'put', | |
| 18 | + data: data | |
| 19 | + }) | |
| 20 | +} | |
| 21 | + | |
| 22 | +// 删除支付渠道 | |
| 23 | +export function deleteChannel(id) { | |
| 24 | + return request({ | |
| 25 | + url: '/pay/channel/delete?id=' + id, | |
| 26 | + method: 'delete' | |
| 27 | + }) | |
| 28 | +} | |
| 29 | + | |
| 30 | +// 获得支付渠道 | |
| 31 | +// export function getChannel(id) { | |
| 32 | +// return request({ | |
| 33 | +// url: '/pay/channel/get?id=' + id, | |
| 34 | +// method: 'get' | |
| 35 | +// }) | |
| 36 | +// } | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | +// 获得支付渠道分页 | |
| 41 | +export function getChannelPage(query) { | |
| 42 | + return request({ | |
| 43 | + url: '/pay/channel/page', | |
| 44 | + method: 'get', | |
| 45 | + params: query | |
| 46 | + }) | |
| 47 | +} | |
| 48 | + | |
| 49 | +// 导出支付渠道Excel | |
| 50 | +export function exportChannelExcel(query) { | |
| 51 | + return request({ | |
| 52 | + url: '/pay/channel/export-excel', | |
| 53 | + method: 'get', | |
| 54 | + params: query, | |
| 55 | + responseType: 'blob' | |
| 56 | + }) | |
| 57 | +} | |
| 58 | + | |
| 59 | +// 获得支付渠道 | |
| 60 | +export function getChannel(merchantId,appId,code) { | |
| 61 | + return request({ | |
| 62 | + url: '/pay/channel/get-channel', | |
| 63 | + params:{ | |
| 64 | + merchantId:merchantId, | |
| 65 | + appId:appId, | |
| 66 | + code:code | |
| 67 | + }, | |
| 68 | + method: 'get' | |
| 69 | + }) | |
| 70 | +} | |
| 71 | + | ... | ... |
yudao-admin-ui/src/api/pay/merchant.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 创建支付商户信息 | |
| 4 | +export function createMerchant(data) { | |
| 5 | + return request({ | |
| 6 | + url: '/pay/merchant/create', | |
| 7 | + method: 'post', | |
| 8 | + data: data | |
| 9 | + }) | |
| 10 | +} | |
| 11 | + | |
| 12 | +// 更新支付商户信息 | |
| 13 | +export function updateMerchant(data) { | |
| 14 | + return request({ | |
| 15 | + url: '/pay/merchant/update', | |
| 16 | + method: 'put', | |
| 17 | + data: data | |
| 18 | + }) | |
| 19 | +} | |
| 20 | + | |
| 21 | +// 支付商户状态修改 | |
| 22 | +export function changeMerchantStatus(id, status) { | |
| 23 | + const data = { | |
| 24 | + id, | |
| 25 | + status | |
| 26 | + } | |
| 27 | + return request({ | |
| 28 | + url: '/pay/merchant/update-status', | |
| 29 | + method: 'put', | |
| 30 | + data: data | |
| 31 | + }) | |
| 32 | +} | |
| 33 | + | |
| 34 | +// 删除支付商户信息 | |
| 35 | +export function deleteMerchant(id) { | |
| 36 | + return request({ | |
| 37 | + url: '/pay/merchant/delete?id=' + id, | |
| 38 | + method: 'delete' | |
| 39 | + }) | |
| 40 | +} | |
| 41 | + | |
| 42 | +// 获得支付商户信息 | |
| 43 | +export function getMerchant(id) { | |
| 44 | + return request({ | |
| 45 | + url: '/pay/merchant/get?id=' + id, | |
| 46 | + method: 'get' | |
| 47 | + }) | |
| 48 | +} | |
| 49 | +// 根据商户名称搜索商户列表 | |
| 50 | +export function getMerchantListByName(name) { | |
| 51 | + return request({ | |
| 52 | + url: '/pay/merchant/list-by-name', | |
| 53 | + params:{ | |
| 54 | + name:name | |
| 55 | + }, | |
| 56 | + method: 'get' | |
| 57 | + }) | |
| 58 | +} | |
| 59 | + | |
| 60 | +// 获得支付商户信息分页 | |
| 61 | +export function getMerchantPage(query) { | |
| 62 | + return request({ | |
| 63 | + url: '/pay/merchant/page', | |
| 64 | + method: 'get', | |
| 65 | + params: query | |
| 66 | + }) | |
| 67 | +} | |
| 68 | + | |
| 69 | +// 导出支付商户信息 Excel | |
| 70 | +export function exportMerchantExcel(query) { | |
| 71 | + return request({ | |
| 72 | + url: '/pay/merchant/export-excel', | |
| 73 | + method: 'get', | |
| 74 | + params: query, | |
| 75 | + responseType: 'blob' | |
| 76 | + }) | |
| 77 | +} | ... | ... |
yudao-admin-ui/src/api/pay/order.js
0 → 100755
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 创建支付订单 | |
| 4 | +export function createOrder(data) { | |
| 5 | + return request({ | |
| 6 | + url: '/pay/order/create', | |
| 7 | + method: 'post', | |
| 8 | + data: data | |
| 9 | + }) | |
| 10 | +} | |
| 11 | + | |
| 12 | +// 更新支付订单 | |
| 13 | +export function updateOrder(data) { | |
| 14 | + return request({ | |
| 15 | + url: '/pay/order/update', | |
| 16 | + method: 'put', | |
| 17 | + data: data | |
| 18 | + }) | |
| 19 | +} | |
| 20 | + | |
| 21 | +// 删除支付订单 | |
| 22 | +export function deleteOrder(id) { | |
| 23 | + return request({ | |
| 24 | + url: '/pay/order/delete?id=' + id, | |
| 25 | + method: 'delete' | |
| 26 | + }) | |
| 27 | +} | |
| 28 | + | |
| 29 | +// 获得支付订单 | |
| 30 | +export function getOrder(id) { | |
| 31 | + return request({ | |
| 32 | + url: '/pay/order/get?id=' + id, | |
| 33 | + method: 'get' | |
| 34 | + }) | |
| 35 | +} | |
| 36 | + | |
| 37 | +// 获得支付订单分页 | |
| 38 | +export function getOrderPage(query) { | |
| 39 | + return request({ | |
| 40 | + url: '/pay/order/page', | |
| 41 | + method: 'get', | |
| 42 | + params: query | |
| 43 | + }) | |
| 44 | +} | |
| 45 | + | |
| 46 | +// 导出支付订单 Excel | |
| 47 | +export function exportOrderExcel(query) { | |
| 48 | + return request({ | |
| 49 | + url: '/pay/order/export-excel', | |
| 50 | + method: 'get', | |
| 51 | + params: query, | |
| 52 | + responseType: 'blob' | |
| 53 | + }) | |
| 54 | +} | ... | ... |
yudao-admin-ui/src/api/pay/refund.js
0 → 100755
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 创建退款订单 | |
| 4 | +export function createRefund(data) { | |
| 5 | + return request({ | |
| 6 | + url: '/pay/refund/create', | |
| 7 | + method: 'post', | |
| 8 | + data: data | |
| 9 | + }) | |
| 10 | +} | |
| 11 | + | |
| 12 | +// 更新退款订单 | |
| 13 | +export function updateRefund(data) { | |
| 14 | + return request({ | |
| 15 | + url: '/pay/refund/update', | |
| 16 | + method: 'put', | |
| 17 | + data: data | |
| 18 | + }) | |
| 19 | +} | |
| 20 | + | |
| 21 | +// 删除退款订单 | |
| 22 | +export function deleteRefund(id) { | |
| 23 | + return request({ | |
| 24 | + url: '/pay/refund/delete?id=' + id, | |
| 25 | + method: 'delete' | |
| 26 | + }) | |
| 27 | +} | |
| 28 | + | |
| 29 | +// 获得退款订单 | |
| 30 | +export function getRefund(id) { | |
| 31 | + return request({ | |
| 32 | + url: '/pay/refund/get?id=' + id, | |
| 33 | + method: 'get' | |
| 34 | + }) | |
| 35 | +} | |
| 36 | + | |
| 37 | +// 获得退款订单分页 | |
| 38 | +export function getRefundPage(query) { | |
| 39 | + return request({ | |
| 40 | + url: '/pay/refund/page', | |
| 41 | + method: 'get', | |
| 42 | + params: query | |
| 43 | + }) | |
| 44 | +} | |
| 45 | + | |
| 46 | +// 导出退款订单 Excel | |
| 47 | +export function exportRefundExcel(query) { | |
| 48 | + return request({ | |
| 49 | + url: '/pay/refund/export-excel', | |
| 50 | + method: 'get', | |
| 51 | + params: query, | |
| 52 | + responseType: 'blob' | |
| 53 | + }) | |
| 54 | +} | ... | ... |
yudao-admin-ui/src/assets/icons/svg/config.svg
0 → 100644
| 1 | +<?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="1635996976125" class="icon" viewBox="0 0 1070 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4431" xmlns:xlink="http://www.w3.org/1999/xlink" width="208.984375" 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"); } | |
| 2 | +</style></defs><path d="M682.216727 1024a35.281455 35.281455 0 0 1-18.618182-7.912727 46.638545 46.638545 0 0 1-12.101818-16.337455l-3.258182-8.378182a19.549091 19.549091 0 0 1-3.258181-4.654545 139.915636 139.915636 0 0 0-35.793455-46.685091 104.448 104.448 0 0 0-134.888727 0c-19.083636 15.080727-33.698909 35.048727-42.356364 57.856a37.748364 37.748364 0 0 1-16.244363 19.083636c-18.757818 7.912727-39.842909 7.912727-58.600728 0a320.791273 320.791273 0 0 1-38.167272-13.498181 185.902545 185.902545 0 0 1-34.397091-19.083637 95.511273 95.511273 0 0 1-20.945455-21.038545 33.652364 33.652364 0 0 1-6.050909-18.152728c-0.465455-10.053818 1.629091-20.014545 6.050909-28.951272 8.238545-18.106182 11.450182-38.074182 9.309091-57.856a100.398545 100.398545 0 0 0-27.927273-59.717818 71.121455 71.121455 0 0 0-37.189818-21.41091 159.557818 159.557818 0 0 0-41.890909-3.723636c-15.825455 0.930909-31.418182 3.909818-46.498909 8.843636a46.405818 46.405818 0 0 1-30.72 0 50.269091 50.269091 0 0 1-22.295273-20.526545 237.661091 237.661091 0 0 1-18.618182-35.002182 219.229091 219.229091 0 0 1-12.567272-39.656727 93.556364 93.556364 0 0 1 0-33.559273 35.002182 35.002182 0 0 1 21.876363-30.813091 154.903273 154.903273 0 0 0 59.112728-43.380363c16.896-18.432 26.344727-42.589091 26.530909-67.630546a96.256 96.256 0 0 0-26.065455-67.165091c-16.337455-18.245818-36.538182-32.581818-59.112727-41.984a30.254545 30.254545 0 0 1-16.290909-15.872 56.087273 56.087273 0 0 1-10.24-27.508363c0.465455-10.891636 2.141091-21.736727 5.12-32.209455a217.367273 217.367273 0 0 1 27.927272-64.372364c5.306182-8.238545 12.288-15.220364 20.48-20.48a22.760727 22.760727 0 0 1 16.756364-4.70109c6.144 0.791273 12.241455 2.234182 18.152727 4.18909 21.643636 8.843636 45.195636 11.729455 68.328728 8.378182 23.738182-3.397818 45.754182-14.336 62.836363-31.232 8.890182-8.843636 15.592727-19.735273 19.549091-31.697454 3.770182-12.334545 6.283636-24.994909 7.447273-37.794909a168.401455 168.401455 0 0 0 0-34.071273c0-9.309091 0-16.756364-2.792727-21.876364a113.105455 113.105455 0 0 1-3.723637-13.591272 23.365818 23.365818 0 0 1 0-16.29091c5.306182-11.636364 14.056727-21.410909 25.088-28.020363 11.450182-7.912727 23.784727-14.429091 36.770909-19.549091 12.520727-4.794182 25.413818-8.517818 38.586182-11.217455 10.379636-2.466909 20.945455-3.909818 31.650909-4.189091a28.811636 28.811636 0 0 1 22.295273 9.309091c5.12 5.538909 9.076364 12.008727 11.636364 19.130182 8.564364 20.48 22.155636 38.446545 39.563636 52.270546 39.330909 29.323636 93.184 29.323636 132.514909 0 19.176727-13.498182 33.792-32.581818 41.890909-54.597819l2.327273-4.654545c3.444364-4.887273 7.354182-9.402182 11.636364-13.498182l3.258181-3.770182c14.848-6.330182 31.650909-6.330182 46.498909 0 12.101818 2.978909 23.924364 7.028364 35.374546 12.101819 11.682909 4.980364 22.667636 11.543273 32.535273 19.595636 9.309091 7.447273 17.361455 16.477091 23.738181 26.624 3.258182 5.771636 4.375273 12.567273 3.258182 19.083636a50.501818 50.501818 0 0 1-5.12 15.872c-9.169455 20.805818-12.101818 43.845818-8.378182 66.234182 3.677091 23.412364 14.754909 45.009455 31.65091 61.579636 17.221818 17.314909 40.261818 27.601455 64.60509 28.951273a142.894545 142.894545 0 0 0 71.214546-12.567273c6.423273-3.816727 13.963636-5.259636 21.364364-4.235636 8.564364 0.279273 16.709818 3.723636 22.807272 9.774546 12.939636 13.312 22.946909 29.184 29.323637 46.68509 8.285091 20.340364 14.056727 41.658182 17.175272 63.441455a38.353455 38.353455 0 0 1-6.050909 28.858182 40.96 40.96 0 0 1-17.221818 14.056727c-22.993455 8.331636-43.147636 23.04-58.135273 42.449455a107.985455 107.985455 0 0 0-25.134545 70.423272c-0.465455 23.365818 6.516364 46.219636 20.014545 65.303273a112.64 112.64 0 0 0 53.061819 40.122182 23.272727 23.272727 0 0 1 10.24 7.447273h2.792727c7.493818 5.957818 13.032727 14.103273 15.778909 23.319272 0.093091 1.396364 0.093091 2.792727 0 4.189091a97.745455 97.745455 0 0 1 0 29.882182c-2.234182 12.939636-5.818182 25.6-10.705455 37.794909-4.840727 12.194909-11.077818 23.738182-18.618181 34.490182a67.025455 67.025455 0 0 1-24.203637 21.922909c-14.475636 7.912727-31.976727 7.912727-46.498909 0a229.236364 229.236364 0 0 0-27.461818-6.050909 131.723636 131.723636 0 0 0-33.466182 0 159.650909 159.650909 0 0 0-33.978182 6.981818 65.582545 65.582545 0 0 0-28.811636 18.664727 108.357818 108.357818 0 0 0-30.72 62.510546c-3.025455 22.900364 0.372364 46.126545 9.774545 67.165091a42.077091 42.077091 0 0 1-3.258181 43.892363 86.574545 86.574545 0 0 1-20.945455 18.152728c-9.914182 6.562909-20.293818 12.334545-31.138909 17.268363a195.444364 195.444364 0 0 1-35.84 12.101819 150.807273 150.807273 0 0 1-31.604364 5.166545z m-378.135272-83.037091l7.912727 6.516364c8.098909 5.771636 16.849455 10.612364 26.065454 14.475636 10.705455 4.561455 21.736727 8.471273 33.000728 11.636364 6.656 2.094545 13.498182 3.351273 20.48 3.723636a179.525818 179.525818 0 0 1 54.411636-72.285091 150.807273 150.807273 0 0 1 194.420364 0c18.944 15.173818 34.722909 33.838545 46.545454 55.063273 2.187636 2.094545 3.956364 4.654545 5.12 7.447273l3.258182 8.843636h12.055273c9.309091-2.187636 18.292364-5.306182 26.996363-9.309091 8.704-3.863273 17.082182-8.378182 25.134546-13.498182l6.981818-4.654545a172.125091 172.125091 0 0 1-13.032727-90.996364 152.669091 152.669091 0 0 1 42.775272-88.622545 111.616 111.616 0 0 1 48.826182-31.232c14.196364-4.701091 28.858182-7.819636 43.752728-9.309091a179.479273 179.479273 0 0 1 46.498909 0c11.636364 1.861818 23.133091 4.468364 34.443636 7.912727h9.262545a22.807273 22.807273 0 0 0 6.981819-7.447273c5.492364-7.866182 10.007273-16.290909 13.498181-25.227636 3.816727-9.309091 6.609455-18.990545 8.378182-28.904727 0.372364-4.189091 0.372364-8.424727 0-12.613818l-3.258182-2.327273A158.673455 158.673455 0 0 1 932.910545 605.090909a155.648 155.648 0 0 1-28.811636-93.277091 153.274182 153.274182 0 0 1 34.443636-97.978182c18.199273-23.412364 42.077091-41.890909 69.306182-53.620363a216.901818 216.901818 0 0 0-13.498182-46.685091 108.311273 108.311273 0 0 0-13.498181-25.6 187.904 187.904 0 0 1-89.786182 14.894545 144.011636 144.011636 0 0 1-92.997818-42.914909 156.392727 156.392727 0 0 1-46.545455-87.226182 165.562182 165.562182 0 0 1 11.170909-90.484363 89.739636 89.739636 0 0 0-29.789091-20.992 161.978182 161.978182 0 0 0-27.880727-9.309091l-13.963636-4.701091a161.373091 161.373091 0 0 1-55.342546 73.216 157.323636 157.323636 0 0 1-190.696727-2.792727 178.641455 178.641455 0 0 1-52.596364-70.423273h-11.636363a204.241455 204.241455 0 0 0-31.138909 9.309091 139.403636 139.403636 0 0 0-27.461819 14.475636l-3.723636 2.792727v6.05091c0 8.843636 2.792727 17.268364 3.723636 27.089454 1.442909 14.242909 1.442909 28.625455 0 42.914909-1.582545 15.825455-4.840727 31.464727-9.774545 46.638546-6.050909 19.549091-16.756364 37.236364-31.138909 51.758545-24.203636 24.064-55.528727 39.563636-89.320727 44.311273a175.336727 175.336727 0 0 1-90.205091-10.24v2.327273a143.825455 143.825455 0 0 0-12.101819 22.388363 170.123636 170.123636 0 0 0-8.843636 26.577455 90.298182 90.298182 0 0 0-3.258182 25.693091A211.176727 211.176727 0 0 1 148.247273 410.530909c24.901818 26.670545 38.725818 61.905455 38.632727 98.443636a146.245818 146.245818 0 0 1-38.167273 97.931637c-19.409455 23.133091-43.752727 41.611636-71.168 54.132363-0.512 4.654545-0.512 9.309091 0 13.963637a175.755636 175.755636 0 0 0 24.669091 58.786909l2.792727 3.723636a198.097455 198.097455 0 0 1 112.081455-6.050909c23.412364 5.12 44.683636 17.361455 60.974545 35.002182a145.687273 145.687273 0 0 1 41.37891 87.691636c2.839273 27.927273-1.815273 56.133818-13.498182 81.640728l-1.861818 5.12zM77.544727 360.261818l-18.618182 13.498182 18.618182-9.774545v-3.723637zM405.922909 25.739636l-17.221818 15.36 3.723636 3.258182 13.498182-18.618182z" p-id="4432"></path><path d="M543.045818 698.181818a186.181818 186.181818 0 1 1 0-372.363636 186.181818 186.181818 0 0 1 0 372.363636z m0-325.818182a139.636364 139.636364 0 1 0 0 279.272728 139.636364 139.636364 0 0 0 0-279.272728z" p-id="4433"></path></svg> | |
| 0 | 3 | \ No newline at end of file | ... | ... |
yudao-admin-ui/src/assets/icons/svg/merchant.svg
0 → 100644
| 1 | +<?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"); } | |
| 2 | +</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> | |
| 0 | 3 | \ No newline at end of file | ... | ... |
yudao-admin-ui/src/assets/icons/svg/order.svg
0 → 100644
| 1 | +<?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"); } | |
| 2 | +</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> | |
| 0 | 3 | \ No newline at end of file | ... | ... |
yudao-admin-ui/src/assets/icons/svg/pay.svg
0 → 100644
| 1 | +<?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"); } | |
| 2 | +</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> | |
| 0 | 3 | \ No newline at end of file | ... | ... |
yudao-admin-ui/src/assets/icons/svg/percentSign.svg
0 → 100644
| 1 | +<?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"); } | |
| 2 | +</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> | |
| 0 | 3 | \ No newline at end of file | ... | ... |
yudao-admin-ui/src/utils/constants.js
| ... | ... | @@ -16,7 +16,7 @@ export const SysCommonStatusEnum = { |
| 16 | 16 | * 菜单的类型枚举 |
| 17 | 17 | */ |
| 18 | 18 | export const SysMenuTypeEnum = { |
| 19 | - DIR : 1, // 目录 | |
| 19 | + DIR: 1, // 目录 | |
| 20 | 20 | MENU: 2, // 菜单 |
| 21 | 21 | BUTTON: 3 // 按钮 |
| 22 | 22 | } |
| ... | ... | @@ -90,3 +90,138 @@ export const SysUserSocialTypeEnum = { |
| 90 | 90 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/wechat_enterprise.png", |
| 91 | 91 | } |
| 92 | 92 | } |
| 93 | + | |
| 94 | +/** | |
| 95 | + * 支付渠道枚举 | |
| 96 | + */ | |
| 97 | +export const PayChannelEnum = { | |
| 98 | + WX_PUB: { | |
| 99 | + "code": "wx_pub", | |
| 100 | + "name": "微信 JSAPI 支付", | |
| 101 | + }, | |
| 102 | + WX_LITE: { | |
| 103 | + "code": "wx_lite", | |
| 104 | + "name": "微信小程序支付" | |
| 105 | + }, | |
| 106 | + WX_APP: { | |
| 107 | + "code": "wx_app", | |
| 108 | + "name": "微信 APP 支付" | |
| 109 | + }, | |
| 110 | + ALIPAY_PC: { | |
| 111 | + "code": "alipay_pc", | |
| 112 | + "name": "支付宝 PC 网站支付" | |
| 113 | + }, | |
| 114 | + ALIPAY_WAP: { | |
| 115 | + "code": "alipay_wap", | |
| 116 | + "name": "支付宝 WAP 网站支付" | |
| 117 | + }, | |
| 118 | + ALIPAY_APP: { | |
| 119 | + "code": "alipay_app", | |
| 120 | + "name": "支付宝 APP 支付" | |
| 121 | + }, | |
| 122 | + ALIPAY_QR: { | |
| 123 | + "code": "alipay_qr", | |
| 124 | + "name": "支付宝扫码支付" | |
| 125 | + }, | |
| 126 | +} | |
| 127 | + | |
| 128 | +/** | |
| 129 | + * 支付类型枚举 | |
| 130 | + */ | |
| 131 | +export const PayType = { | |
| 132 | + WECHAT: "WECHAT", | |
| 133 | + ALIPAY: "ALIPAY" | |
| 134 | +} | |
| 135 | + | |
| 136 | +/** | |
| 137 | + * 支付订单状态枚举 | |
| 138 | + */ | |
| 139 | +export const payOrderStatusEnum = { | |
| 140 | + WAITING: { | |
| 141 | + status: 0, | |
| 142 | + name: '未支付' | |
| 143 | + }, | |
| 144 | + SUCCESS: { | |
| 145 | + status: 10, | |
| 146 | + name: '已支付' | |
| 147 | + }, | |
| 148 | + CLOSED: { | |
| 149 | + status: 20, | |
| 150 | + name: '未支付' | |
| 151 | + } | |
| 152 | +} | |
| 153 | + | |
| 154 | +/** | |
| 155 | + * 支付订单回调状态枚举 | |
| 156 | + */ | |
| 157 | +export const payOrderNotifyStatusEnum = { | |
| 158 | + NO: { | |
| 159 | + status: 0, | |
| 160 | + name: '未通知' | |
| 161 | + }, | |
| 162 | + SUCCESS: { | |
| 163 | + status: 10, | |
| 164 | + name: '通知成功' | |
| 165 | + }, | |
| 166 | + FAILURE: { | |
| 167 | + status: 20, | |
| 168 | + name: '通知失败' | |
| 169 | + } | |
| 170 | +} | |
| 171 | + | |
| 172 | +/** | |
| 173 | + * 支付订单退款状态枚举 | |
| 174 | + */ | |
| 175 | +export const payOrderRefundStatusEnum = { | |
| 176 | + NO: { | |
| 177 | + status: 0, | |
| 178 | + name: '未退款' | |
| 179 | + }, | |
| 180 | + SOME: { | |
| 181 | + status: 10, | |
| 182 | + name: '部分退款' | |
| 183 | + }, | |
| 184 | + ALL: { | |
| 185 | + status: 20, | |
| 186 | + name: '全部退款' | |
| 187 | + } | |
| 188 | +} | |
| 189 | + | |
| 190 | +/** | |
| 191 | + * 支付退款订单状态枚举 | |
| 192 | + */ | |
| 193 | +export const payRefundStatusEnum = { | |
| 194 | + CREATE:{ | |
| 195 | + status:0, | |
| 196 | + name: '退款订单生成' | |
| 197 | + }, | |
| 198 | + SUCCESS:{ | |
| 199 | + status:1, | |
| 200 | + name: '退款成功' | |
| 201 | + }, | |
| 202 | + FAILURE:{ | |
| 203 | + status:2, | |
| 204 | + name: '退款失败' | |
| 205 | + }, | |
| 206 | + PROCESSING_NOTIFY:{ | |
| 207 | + status:3, | |
| 208 | + name: '退款中,渠道通知结果' | |
| 209 | + }, | |
| 210 | + PROCESSING_QUERY:{ | |
| 211 | + status:4, | |
| 212 | + name: '退款中,系统查询结果' | |
| 213 | + }, | |
| 214 | + UNKNOWN_RETRY:{ | |
| 215 | + status:5, | |
| 216 | + name: '状态未知,请重试' | |
| 217 | + }, | |
| 218 | + UNKNOWN_QUERY:{ | |
| 219 | + status:6, | |
| 220 | + name: '状态未知,系统查询结果' | |
| 221 | + }, | |
| 222 | + CLOSE:{ | |
| 223 | + status:99, | |
| 224 | + name: '退款关闭' | |
| 225 | + } | |
| 226 | +} | |
| 227 | + | ... | ... |
yudao-admin-ui/src/utils/dict.js
| ... | ... | @@ -41,8 +41,29 @@ export const DICT_TYPE = { |
| 41 | 41 | BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status', |
| 42 | 42 | BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result', |
| 43 | 43 | BPM_TASK_ASSIGN_SCRIPT: 'bpm_task_assign_script', |
| 44 | - OA_LEAVE_STATUS: 'flow_status', // todo 芋艿:可以删除 | |
| 45 | - BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type' | |
| 44 | + BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type', | |
| 45 | + | |
| 46 | + // pay | |
| 47 | + // 微信渠道版本 | |
| 48 | + PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version', | |
| 49 | + // 支付渠道支付宝算法类型 | |
| 50 | + PAY_CHANNEL_ALIPAY_SIGN_TYPE:'pay_channel_alipay_sign_type', | |
| 51 | + // 支付宝公钥类型 | |
| 52 | + PAY_CHANNEL_ALIPAY_MODE:'pay_channel_alipay_mode', | |
| 53 | + // 支付宝网关地址 | |
| 54 | + PAY_CHANNEL_ALIPAY_SERVER_TYPE:'pay_channel_alipay_server_type', | |
| 55 | + // 支付渠道编码类型 | |
| 56 | + PAY_CHANNEL_CODE_TYPE: 'pay_channel_code_type', | |
| 57 | + // 商户支付订单回调状态 | |
| 58 | + PAY_ORDER_NOTIFY_STATUS: 'pay_order_notify_status', | |
| 59 | + // 商户支付订单状态 | |
| 60 | + PAY_ORDER_STATUS: 'pay_order_status', | |
| 61 | + // 商户支付订单退款状态 | |
| 62 | + PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status', | |
| 63 | + // 退款订单状态 | |
| 64 | + PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', | |
| 65 | + // 退款订单类别 | |
| 66 | + PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', | |
| 46 | 67 | } |
| 47 | 68 | |
| 48 | 69 | /** | ... | ... |
yudao-admin-ui/src/utils/ruoyi.js
| ... | ... | @@ -7,66 +7,68 @@ const baseURL = process.env.VUE_APP_BASE_API |
| 7 | 7 | |
| 8 | 8 | // 日期格式化 |
| 9 | 9 | export function parseTime(time, pattern) { |
| 10 | - if (arguments.length === 0 || !time) { | |
| 11 | - return null | |
| 12 | - } | |
| 13 | - const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' | |
| 14 | - let date | |
| 15 | - if (typeof time === 'object') { | |
| 16 | - date = time | |
| 17 | - } else { | |
| 18 | - if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { | |
| 19 | - time = parseInt(time) | |
| 20 | - } else if (typeof time === 'string') { | |
| 21 | - time = time.replace(new RegExp(/-/gm), '/'); | |
| 22 | - } | |
| 23 | - if ((typeof time === 'number') && (time.toString().length === 10)) { | |
| 24 | - time = time * 1000 | |
| 25 | - } | |
| 26 | - date = new Date(time) | |
| 27 | - } | |
| 28 | - const formatObj = { | |
| 29 | - y: date.getFullYear(), | |
| 30 | - m: date.getMonth() + 1, | |
| 31 | - d: date.getDate(), | |
| 32 | - h: date.getHours(), | |
| 33 | - i: date.getMinutes(), | |
| 34 | - s: date.getSeconds(), | |
| 35 | - a: date.getDay() | |
| 36 | - } | |
| 37 | - const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { | |
| 38 | - let value = formatObj[key] | |
| 39 | - // Note: getDay() returns 0 on Sunday | |
| 40 | - if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } | |
| 41 | - if (result.length > 0 && value < 10) { | |
| 42 | - value = '0' + value | |
| 43 | - } | |
| 44 | - return value || 0 | |
| 45 | - }) | |
| 46 | - return time_str | |
| 10 | + if (arguments.length === 0 || !time) { | |
| 11 | + return null | |
| 12 | + } | |
| 13 | + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' | |
| 14 | + let date | |
| 15 | + if (typeof time === 'object') { | |
| 16 | + date = time | |
| 17 | + } else { | |
| 18 | + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { | |
| 19 | + time = parseInt(time) | |
| 20 | + } else if (typeof time === 'string') { | |
| 21 | + time = time.replace(new RegExp(/-/gm), '/'); | |
| 22 | + } | |
| 23 | + if ((typeof time === 'number') && (time.toString().length === 10)) { | |
| 24 | + time = time * 1000 | |
| 25 | + } | |
| 26 | + date = new Date(time) | |
| 27 | + } | |
| 28 | + const formatObj = { | |
| 29 | + y: date.getFullYear(), | |
| 30 | + m: date.getMonth() + 1, | |
| 31 | + d: date.getDate(), | |
| 32 | + h: date.getHours(), | |
| 33 | + i: date.getMinutes(), | |
| 34 | + s: date.getSeconds(), | |
| 35 | + a: date.getDay() | |
| 36 | + } | |
| 37 | + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { | |
| 38 | + let value = formatObj[key] | |
| 39 | + // Note: getDay() returns 0 on Sunday | |
| 40 | + if (key === 'a') { | |
| 41 | + return ['日', '一', '二', '三', '四', '五', '六'][value] | |
| 42 | + } | |
| 43 | + if (result.length > 0 && value < 10) { | |
| 44 | + value = '0' + value | |
| 45 | + } | |
| 46 | + return value || 0 | |
| 47 | + }) | |
| 48 | + return time_str | |
| 47 | 49 | } |
| 48 | 50 | |
| 49 | 51 | // 表单重置 |
| 50 | 52 | export function resetForm(refName) { |
| 51 | - if (this.$refs[refName]) { | |
| 52 | - this.$refs[refName].resetFields(); | |
| 53 | - } | |
| 53 | + if (this.$refs[refName]) { | |
| 54 | + this.$refs[refName].resetFields(); | |
| 55 | + } | |
| 54 | 56 | } |
| 55 | 57 | |
| 56 | 58 | // 添加日期范围 |
| 57 | 59 | export function addDateRange(params, dateRange, propName) { |
| 58 | 60 | const search = params; |
| 59 | 61 | search.params = {}; |
| 60 | - if (null != dateRange && '' !== dateRange) { | |
| 61 | - if (typeof(propName) === "undefined") { | |
| 62 | - search["beginTime"] = dateRange[0]; | |
| 63 | - search["endTime"] = dateRange[1]; | |
| 64 | - } else { | |
| 65 | - search["begin" + propName] = dateRange[0]; | |
| 66 | - search["end" + propName] = dateRange[1]; | |
| 67 | - } | |
| 68 | - } | |
| 69 | - return search; | |
| 62 | + if (null != dateRange && '' !== dateRange) { | |
| 63 | + if (typeof (propName) === "undefined") { | |
| 64 | + search["beginTime"] = dateRange[0]; | |
| 65 | + search["endTime"] = dateRange[1]; | |
| 66 | + } else { | |
| 67 | + search["begin" + propName] = dateRange[0]; | |
| 68 | + search["end" + propName] = dateRange[1]; | |
| 69 | + } | |
| 70 | + } | |
| 71 | + return search; | |
| 70 | 72 | } |
| 71 | 73 | |
| 72 | 74 | /** |
| ... | ... | @@ -98,21 +100,21 @@ export function addBeginAndEndTime(params, dateRange, propName) { |
| 98 | 100 | return params; |
| 99 | 101 | } |
| 100 | 102 | |
| 101 | -// 回显数据字典 | |
| 103 | +// 回显数据字典 原若依所保留,请使用 dict.js 中的新方法 | |
| 102 | 104 | export function selectDictLabel(datas, value) { |
| 103 | - var actions = []; | |
| 104 | - Object.keys(datas).some((key) => { | |
| 105 | - if (datas[key].dictValue == ('' + value)) { | |
| 106 | - actions.push(datas[key].dictLabel); | |
| 107 | - return true; | |
| 108 | - } | |
| 109 | - }) | |
| 110 | - return actions.join(''); | |
| 105 | + var actions = []; | |
| 106 | + Object.keys(datas).some((key) => { | |
| 107 | + if (datas[key].dictValue == ('' + value)) { | |
| 108 | + actions.push(datas[key].dictLabel); | |
| 109 | + return true; | |
| 110 | + } | |
| 111 | + }) | |
| 112 | + return actions.join(''); | |
| 111 | 113 | } |
| 112 | 114 | |
| 113 | 115 | // 通用下载方法 |
| 114 | 116 | export function download(fileName) { |
| 115 | - window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true; | |
| 117 | + window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true; | |
| 116 | 118 | } |
| 117 | 119 | |
| 118 | 120 | // 下载 Excel 方法 |
| ... | ... | @@ -147,7 +149,7 @@ function download0(data, fileName, mineType) { |
| 147 | 149 | window.URL = window.URL || window.webkitURL; |
| 148 | 150 | let href = URL.createObjectURL(blob); |
| 149 | 151 | let downA = document.createElement("a"); |
| 150 | - downA.href = href; | |
| 152 | + downA.href = href; | |
| 151 | 153 | downA.download = fileName; |
| 152 | 154 | downA.click(); |
| 153 | 155 | // 销毁超连接 |
| ... | ... | @@ -156,24 +158,24 @@ function download0(data, fileName, mineType) { |
| 156 | 158 | |
| 157 | 159 | // 字符串格式化(%s ) |
| 158 | 160 | export function sprintf(str) { |
| 159 | - var args = arguments, flag = true, i = 1; | |
| 160 | - str = str.replace(/%s/g, function () { | |
| 161 | - var arg = args[i++]; | |
| 162 | - if (typeof arg === 'undefined') { | |
| 163 | - flag = false; | |
| 164 | - return ''; | |
| 165 | - } | |
| 166 | - return arg; | |
| 167 | - }); | |
| 168 | - return flag ? str : ''; | |
| 161 | + var args = arguments, flag = true, i = 1; | |
| 162 | + str = str.replace(/%s/g, function () { | |
| 163 | + var arg = args[i++]; | |
| 164 | + if (typeof arg === 'undefined') { | |
| 165 | + flag = false; | |
| 166 | + return ''; | |
| 167 | + } | |
| 168 | + return arg; | |
| 169 | + }); | |
| 170 | + return flag ? str : ''; | |
| 169 | 171 | } |
| 170 | 172 | |
| 171 | 173 | // 转换字符串,undefined,null等转化为"" |
| 172 | 174 | export function praseStrEmpty(str) { |
| 173 | - if (!str || str == "undefined" || str == "null") { | |
| 174 | - return ""; | |
| 175 | - } | |
| 176 | - return str; | |
| 175 | + if (!str || str == "undefined" || str == "null") { | |
| 176 | + return ""; | |
| 177 | + } | |
| 178 | + return str; | |
| 177 | 179 | } |
| 178 | 180 | |
| 179 | 181 | /** |
| ... | ... | @@ -185,21 +187,42 @@ export function praseStrEmpty(str) { |
| 185 | 187 | * @param {*} rootId 根Id 默认 0 |
| 186 | 188 | */ |
| 187 | 189 | export function handleTree(data, id, parentId, children, rootId) { |
| 188 | - id = id || 'id' | |
| 189 | - parentId = parentId || 'parentId' | |
| 190 | - children = children || 'children' | |
| 191 | - rootId = rootId || Math.min.apply(Math, data.map(item => { return item[parentId] })) || 0 | |
| 192 | - //对源数据深度克隆 | |
| 193 | - const cloneData = JSON.parse(JSON.stringify(data)) | |
| 194 | - //循环所有项 | |
| 195 | - const treeData = cloneData.filter(father => { | |
| 196 | - let branchArr = cloneData.filter(child => { | |
| 197 | - //返回每一项的子级数组 | |
| 198 | - return father[id] === child[parentId] | |
| 199 | - }); | |
| 200 | - branchArr.length > 0 ? father.children = branchArr : ''; | |
| 201 | - //返回第一层 | |
| 202 | - return father[parentId] === rootId; | |
| 203 | - }); | |
| 204 | - return treeData !== '' ? treeData : data; | |
| 190 | + id = id || 'id' | |
| 191 | + parentId = parentId || 'parentId' | |
| 192 | + children = children || 'children' | |
| 193 | + rootId = rootId || Math.min.apply(Math, data.map(item => { | |
| 194 | + return item[parentId] | |
| 195 | + })) || 0 | |
| 196 | + //对源数据深度克隆 | |
| 197 | + const cloneData = JSON.parse(JSON.stringify(data)) | |
| 198 | + //循环所有项 | |
| 199 | + const treeData = cloneData.filter(father => { | |
| 200 | + let branchArr = cloneData.filter(child => { | |
| 201 | + //返回每一项的子级数组 | |
| 202 | + return father[id] === child[parentId] | |
| 203 | + }); | |
| 204 | + branchArr.length > 0 ? father.children = branchArr : ''; | |
| 205 | + //返回第一层 | |
| 206 | + return father[parentId] === rootId; | |
| 207 | + }); | |
| 208 | + return treeData !== '' ? treeData : data; | |
| 209 | +} | |
| 210 | + | |
| 211 | +/** | |
| 212 | + * 获取当前时间 | |
| 213 | + * @param timeStr 时分秒 字符串 格式为 xx:xx:xx | |
| 214 | + */ | |
| 215 | +export function getNowDateTime(timeStr) { | |
| 216 | + let now = new Date(); | |
| 217 | + let year = now.getFullYear(); //得到年份 | |
| 218 | + let month = (now.getMonth() + 1).toString().padStart(2, "0"); //得到月份 | |
| 219 | + let day = now.getDate().toString().padStart(2, "0"); //得到日期 | |
| 220 | + | |
| 221 | + if (timeStr != null) { | |
| 222 | + return `${year}-${month}-${day} ${timeStr}`; | |
| 223 | + } | |
| 224 | + let hours = now.getHours().toString().padStart(2, "0") // 得到小时; | |
| 225 | + let minutes = now.getMinutes().toString().padStart(2, "0") // 得到分钟; | |
| 226 | + let seconds = now.getSeconds().toString().padStart(2, "0") // 得到秒; | |
| 227 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | |
| 205 | 228 | } | ... | ... |
yudao-admin-ui/src/views/pay/app/components/aliPayChannelForm.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px"> | |
| 4 | + <el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px" | |
| 5 | + v-loading="transferParam.loading"> | |
| 6 | + <el-form-item label-width="180px" label="渠道费率" prop="feeRate"> | |
| 7 | + <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}"> | |
| 8 | + <template slot="append">%</template> | |
| 9 | + </el-input> | |
| 10 | + </el-form-item> | |
| 11 | + <el-form-item label-width="180px" label="开放平台APPID" prop="aliPayConfig.appId"> | |
| 12 | + <el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :style="{width: '100%'}"> | |
| 13 | + </el-input> | |
| 14 | + </el-form-item> | |
| 15 | + <el-form-item label-width="180px" label="渠道状态" prop="status"> | |
| 16 | + <el-radio-group v-model="form.status" size="medium"> | |
| 17 | + <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | |
| 18 | + {{ dict.label }} | |
| 19 | + </el-radio> | |
| 20 | + </el-radio-group> | |
| 21 | + </el-form-item> | |
| 22 | + <el-form-item label-width="180px" label="网关地址" prop="aliPayConfig.serverUrl"> | |
| 23 | + <el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium"> | |
| 24 | + <el-radio v-for="dict in aliPayServerDatas" :key="dict.value" :label="dict.value"> | |
| 25 | + {{ dict.label }} | |
| 26 | + </el-radio> | |
| 27 | + </el-radio-group> | |
| 28 | + </el-form-item> | |
| 29 | + <el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType"> | |
| 30 | + <el-radio-group v-model="form.aliPayConfig.signType" size="medium"> | |
| 31 | + <el-radio v-for="dict in aliPaySignTypeDatas" :key="dict.value" :label="dict.value"> | |
| 32 | + {{ dict.label }} | |
| 33 | + </el-radio> | |
| 34 | + </el-radio-group> | |
| 35 | + </el-form-item> | |
| 36 | + <el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode"> | |
| 37 | + <el-radio-group v-model="form.aliPayConfig.mode" size="medium"> | |
| 38 | + <el-radio v-for="dict in aliPayModeDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | |
| 39 | + {{ dict.label }} | |
| 40 | + </el-radio> | |
| 41 | + </el-radio-group> | |
| 42 | + </el-form-item> | |
| 43 | + <div v-if="form.aliPayConfig.mode === 1"> | |
| 44 | + <el-form-item label-width="180px" label="商户私钥" prop="aliPayConfig.privateKey"> | |
| 45 | + <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey" | |
| 46 | + placeholder="请输入商户私钥" clearable :style="{width: '100%'}"> | |
| 47 | + </el-input> | |
| 48 | + </el-form-item> | |
| 49 | + <el-form-item label-width="180px" label="支付宝公钥字符串" prop="aliPayConfig.alipayPublicKey"> | |
| 50 | + <el-input | |
| 51 | + type="textarea" | |
| 52 | + :autosize="{minRows: 8, maxRows: 8}" | |
| 53 | + v-model="form.aliPayConfig.alipayPublicKey" | |
| 54 | + placeholder="请输入支付宝公钥字符串" clearable | |
| 55 | + :style="{width: '100%'}"> | |
| 56 | + </el-input> | |
| 57 | + </el-form-item> | |
| 58 | + </div> | |
| 59 | + <div v-if="form.aliPayConfig.mode === 2"> | |
| 60 | + <el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent"> | |
| 61 | + <el-input v-model="form.aliPayConfig.appCertContent" type="textarea" | |
| 62 | + placeholder="请上传商户公钥应用证书" | |
| 63 | + readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | |
| 64 | + </el-form-item> | |
| 65 | + <el-form-item label-width="180px" label=""> | |
| 66 | + <el-upload | |
| 67 | + action="" | |
| 68 | + ref="privateKeyContentFile" | |
| 69 | + :limit="1" | |
| 70 | + :accept="fileAccept" | |
| 71 | + :http-request="appCertUpload" | |
| 72 | + :before-upload="fileBeforeUpload"> | |
| 73 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | |
| 74 | + </el-upload> | |
| 75 | + </el-form-item> | |
| 76 | + <el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent"> | |
| 77 | + <el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea" | |
| 78 | + placeholder="请上传支付宝公钥证书" | |
| 79 | + readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | |
| 80 | + </el-form-item> | |
| 81 | + <el-form-item label-width="180px" label=""> | |
| 82 | + <el-upload | |
| 83 | + ref="privateCertContentFile" | |
| 84 | + action="" | |
| 85 | + :limit="1" | |
| 86 | + :accept="fileAccept" | |
| 87 | + :before-upload="fileBeforeUpload" | |
| 88 | + :http-request="alipayPublicCertUpload"> | |
| 89 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | |
| 90 | + </el-upload> | |
| 91 | + </el-form-item> | |
| 92 | + <el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent"> | |
| 93 | + <el-input | |
| 94 | + v-model="form.aliPayConfig.rootCertContent" | |
| 95 | + type="textarea" | |
| 96 | + placeholder="请上传根证书" | |
| 97 | + readonly :autosize="{minRows: 8, maxRows: 8}" | |
| 98 | + :style="{width: '100%'}"> | |
| 99 | + </el-input> | |
| 100 | + </el-form-item> | |
| 101 | + <el-form-item label-width="180px" label=""> | |
| 102 | + <el-upload | |
| 103 | + ref="privateCertContentFile" | |
| 104 | + :limit="1" | |
| 105 | + :accept="fileAccept" | |
| 106 | + action="" | |
| 107 | + :before-upload="fileBeforeUpload" | |
| 108 | + :http-request="rootCertUpload"> | |
| 109 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | |
| 110 | + </el-upload> | |
| 111 | + </el-form-item> | |
| 112 | + </div> | |
| 113 | + <el-form-item label-width="180px" label="备注" prop="remark"> | |
| 114 | + <el-input v-model="form.remark" :style="{width: '100%'}"></el-input> | |
| 115 | + </el-form-item> | |
| 116 | + </el-form> | |
| 117 | + <div slot="footer" class="dialog-footer"> | |
| 118 | + <el-button @click="close">取消</el-button> | |
| 119 | + <el-button type="primary" @click="handleConfirm">确定</el-button> | |
| 120 | + </div> | |
| 121 | + </el-dialog> | |
| 122 | + </div> | |
| 123 | +</template> | |
| 124 | +<script> | |
| 125 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | |
| 126 | +import {createChannel, getChannel, updateChannel} from "@/api/pay/channel"; | |
| 127 | + | |
| 128 | +const defaultForm = { | |
| 129 | + code: '', | |
| 130 | + status: null, | |
| 131 | + remark: '', | |
| 132 | + feeRate: null, | |
| 133 | + appId: '', | |
| 134 | + merchantId: null, | |
| 135 | + aliPayConfig: { | |
| 136 | + appId: '', | |
| 137 | + serverUrl: null, | |
| 138 | + signType: '', | |
| 139 | + mode: null, | |
| 140 | + privateKey: '', | |
| 141 | + alipayPublicKey: '', | |
| 142 | + appCertContent: '', | |
| 143 | + alipayPublicCertContent: '', | |
| 144 | + rootCertContent: '' | |
| 145 | + } | |
| 146 | +}; | |
| 147 | + | |
| 148 | +export default { | |
| 149 | + name: "aliPayChannelForm", | |
| 150 | + components: {}, | |
| 151 | + props: { | |
| 152 | + // 传输的参数 | |
| 153 | + transferParam: { | |
| 154 | + // 加载动画 | |
| 155 | + "loading": false, | |
| 156 | + // 是否修改 | |
| 157 | + "edit": false, | |
| 158 | + // 是否显示 | |
| 159 | + "aliPayOpen": false, | |
| 160 | + // 应用ID | |
| 161 | + "appId": null, | |
| 162 | + // 渠道编码 | |
| 163 | + "payCode": null, | |
| 164 | + // 商户对象 | |
| 165 | + "payMerchant": { | |
| 166 | + // 编号 | |
| 167 | + "id": null, | |
| 168 | + // 名称 | |
| 169 | + "name": null | |
| 170 | + }, | |
| 171 | + } | |
| 172 | + }, | |
| 173 | + data() { | |
| 174 | + return { | |
| 175 | + title:'', | |
| 176 | + form: JSON.parse(JSON.stringify(defaultForm)), | |
| 177 | + rules: { | |
| 178 | + feeRate: [{ | |
| 179 | + required: true, | |
| 180 | + message: '请输入渠道费率', | |
| 181 | + trigger: 'blur' | |
| 182 | + }], | |
| 183 | + 'aliPayConfig.appId': [{ | |
| 184 | + required: true, | |
| 185 | + message: '请输入开放平台上创建的应用的 ID', | |
| 186 | + trigger: 'blur' | |
| 187 | + }], | |
| 188 | + status: [{ | |
| 189 | + required: true, | |
| 190 | + message: '渠道状态不能为空', | |
| 191 | + trigger: 'blur' | |
| 192 | + }], | |
| 193 | + 'aliPayConfig.serverUrl': [{ | |
| 194 | + required: true, | |
| 195 | + message: '请传入网关地址', | |
| 196 | + trigger: 'blur' | |
| 197 | + }], | |
| 198 | + 'aliPayConfig.signType': [{ | |
| 199 | + required: true, | |
| 200 | + message: '请传入签名算法类型', | |
| 201 | + trigger: 'blur' | |
| 202 | + }], | |
| 203 | + 'aliPayConfig.mode': [{ | |
| 204 | + required: true, | |
| 205 | + message: '公钥类型不能为空', | |
| 206 | + trigger: 'blur' | |
| 207 | + }], | |
| 208 | + 'aliPayConfig.privateKey': [{ | |
| 209 | + required: true, | |
| 210 | + message: '请输入商户私钥', | |
| 211 | + trigger: 'blur' | |
| 212 | + }], | |
| 213 | + 'aliPayConfig.alipayPublicKey': [{ | |
| 214 | + required: true, | |
| 215 | + message: '请输入支付宝公钥字符串', | |
| 216 | + trigger: 'blur' | |
| 217 | + }], | |
| 218 | + 'aliPayConfig.appCertContent': [{ | |
| 219 | + required: true, | |
| 220 | + message: '请上传商户公钥应用证书', | |
| 221 | + trigger: 'blur' | |
| 222 | + }], | |
| 223 | + 'aliPayConfig.alipayPublicCertContent': [{ | |
| 224 | + required: true, | |
| 225 | + message: '请上传支付宝公钥证书', | |
| 226 | + trigger: 'blur' | |
| 227 | + }], | |
| 228 | + 'aliPayConfig.rootCertContent': [{ | |
| 229 | + required: true, | |
| 230 | + message: '请上传指定根证书', | |
| 231 | + trigger: 'blur' | |
| 232 | + }], | |
| 233 | + }, | |
| 234 | + fileAccept: ".crt", | |
| 235 | + // 渠道状态 数据字典 | |
| 236 | + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS), | |
| 237 | + // 支付宝加密方式 | |
| 238 | + aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE), | |
| 239 | + // 版本状态 数据字典 | |
| 240 | + aliPayModeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_MODE), | |
| 241 | + // 支付宝网关地址 | |
| 242 | + aliPayServerDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SERVER_TYPE), | |
| 243 | + } | |
| 244 | + }, | |
| 245 | + watch: { | |
| 246 | + transferParam: { | |
| 247 | + deep: true, // 深度监听 | |
| 248 | + handler(newVal) { | |
| 249 | + if (newVal.aliPayOpen) { | |
| 250 | + this.form.code = newVal.payCode; | |
| 251 | + this.form.appId = newVal.appId; | |
| 252 | + this.form.merchantId = newVal.payMerchant.id; | |
| 253 | + // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据 | |
| 254 | + if (newVal.edit === true && newVal.loading) { | |
| 255 | + this.title = "编辑支付渠道"; | |
| 256 | + this.init(); | |
| 257 | + } else { | |
| 258 | + this.title = "创建支付渠道"; | |
| 259 | + } | |
| 260 | + } | |
| 261 | + } | |
| 262 | + } | |
| 263 | + }, | |
| 264 | + | |
| 265 | + methods: { | |
| 266 | + init() { | |
| 267 | + getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode) | |
| 268 | + .then(response => { | |
| 269 | + this.form.id = response.data.id; | |
| 270 | + this.form.feeRate = response.data.feeRate; | |
| 271 | + this.form.status = response.data.status; | |
| 272 | + this.form.remark = response.data.remark; | |
| 273 | + | |
| 274 | + let config = JSON.parse(response.data.config); | |
| 275 | + this.form.aliPayConfig.appId = config.appId; | |
| 276 | + this.form.aliPayConfig.serverUrl = config.serverUrl; | |
| 277 | + this.form.aliPayConfig.signType = config.signType; | |
| 278 | + this.form.aliPayConfig.mode = config.mode; | |
| 279 | + this.form.aliPayConfig.privateKey = config.privateKey; | |
| 280 | + this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey; | |
| 281 | + this.form.aliPayConfig.appCertContent = config.appCertContent; | |
| 282 | + this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent; | |
| 283 | + this.form.aliPayConfig.rootCertContent = config.rootCertContent; | |
| 284 | + this.transferParam.loading = false; | |
| 285 | + }) | |
| 286 | + }, | |
| 287 | + close() { | |
| 288 | + this.transferParam.aliPayOpen = false; | |
| 289 | + this.form = JSON.parse(JSON.stringify(defaultForm)); | |
| 290 | + }, | |
| 291 | + handleConfirm() { | |
| 292 | + this.$refs['aliPayForm'].validate(valid => { | |
| 293 | + if (!valid) { | |
| 294 | + return | |
| 295 | + } | |
| 296 | + let data = this.form; | |
| 297 | + data.config = JSON.stringify(this.form.aliPayConfig); | |
| 298 | + if (this.transferParam.edit) { | |
| 299 | + updateChannel(data).then(response => { | |
| 300 | + if (response.code === 0) { | |
| 301 | + this.msgSuccess("修改成功"); | |
| 302 | + this.close(); | |
| 303 | + } | |
| 304 | + | |
| 305 | + }) | |
| 306 | + } else { | |
| 307 | + | |
| 308 | + createChannel(data).then(response => { | |
| 309 | + if (response.code === 0) { | |
| 310 | + this.msgSuccess("新增成功"); | |
| 311 | + this.$parent.refreshTable(); | |
| 312 | + this.close(); | |
| 313 | + } | |
| 314 | + }); | |
| 315 | + } | |
| 316 | + }); | |
| 317 | + }, | |
| 318 | + fileBeforeUpload(file) { | |
| 319 | + let format = '.' + file.name.split(".")[1]; | |
| 320 | + if (format !== this.fileAccept) { | |
| 321 | + this.$message.error('请上传指定格式"' + this.fileAccept + '"文件'); | |
| 322 | + return false; | |
| 323 | + } | |
| 324 | + let isRightSize = file.size / 1024 / 1024 < 2 | |
| 325 | + if (!isRightSize) { | |
| 326 | + this.$message.error('文件大小超过 2MB') | |
| 327 | + } | |
| 328 | + return isRightSize | |
| 329 | + }, | |
| 330 | + appCertUpload(event) { | |
| 331 | + const readFile = new FileReader() | |
| 332 | + readFile.onload = (e) => { | |
| 333 | + this.form.aliPayConfig.appCertContent = e.target.result | |
| 334 | + } | |
| 335 | + readFile.readAsText(event.file); | |
| 336 | + }, | |
| 337 | + alipayPublicCertUpload(event) { | |
| 338 | + const readFile = new FileReader() | |
| 339 | + readFile.onload = (e) => { | |
| 340 | + this.form.aliPayConfig.alipayPublicCertContent = e.target.result | |
| 341 | + } | |
| 342 | + readFile.readAsText(event.file); | |
| 343 | + }, | |
| 344 | + rootCertUpload(event) { | |
| 345 | + const readFile = new FileReader() | |
| 346 | + readFile.onload = (e) => { | |
| 347 | + this.form.aliPayConfig.rootCertContent = e.target.result | |
| 348 | + } | |
| 349 | + readFile.readAsText(event.file); | |
| 350 | + }, | |
| 351 | + | |
| 352 | + } | |
| 353 | +} | |
| 354 | + | |
| 355 | +</script> | |
| 356 | +<style scoped> | |
| 357 | + | |
| 358 | +</style> | ... | ... |
yudao-admin-ui/src/views/pay/app/components/wechatChannelForm.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px"> | |
| 4 | + <el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px" | |
| 5 | + v-loading="transferParam.loading"> | |
| 6 | + <el-form-item label-width="180px" label="渠道费率" prop="feeRate"> | |
| 7 | + <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}"> | |
| 8 | + <template slot="append">%</template> | |
| 9 | + </el-input> | |
| 10 | + </el-form-item> | |
| 11 | + <el-form-item label-width="180px" label="公众号APPID" prop="weChatConfig.appId"> | |
| 12 | + <el-input v-model="form.weChatConfig.appId" placeholder="请输入公众号APPID" clearable :style="{width: '100%'}"> | |
| 13 | + </el-input> | |
| 14 | + </el-form-item> | |
| 15 | + <el-form-item label-width="180px" label="商户号" prop="weChatConfig.mchId"> | |
| 16 | + <el-input v-model="form.weChatConfig.mchId" :style="{width: '100%'}"></el-input> | |
| 17 | + </el-form-item> | |
| 18 | + <el-form-item label-width="180px" label="渠道状态" prop="status"> | |
| 19 | + <el-radio-group v-model="form.status" size="medium"> | |
| 20 | + <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | |
| 21 | + {{ dict.label }} | |
| 22 | + </el-radio> | |
| 23 | + </el-radio-group> | |
| 24 | + </el-form-item> | |
| 25 | + <el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion"> | |
| 26 | + <el-radio-group v-model="form.weChatConfig.apiVersion" size="medium"> | |
| 27 | + <el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value"> | |
| 28 | + {{ dict.label }} | |
| 29 | + </el-radio> | |
| 30 | + </el-radio-group> | |
| 31 | + </el-form-item> | |
| 32 | + <el-form-item label-width="180px" label="商户秘钥" prop="weChatConfig.mchKey" | |
| 33 | + v-if="form.weChatConfig.apiVersion === 'v2'"> | |
| 34 | + <el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户秘钥" clearable | |
| 35 | + :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input> | |
| 36 | + </el-form-item> | |
| 37 | + <div v-if="form.weChatConfig.apiVersion === 'v3'"> | |
| 38 | + <el-form-item label-width="180px" label="API V3秘钥" prop="weChatConfig.apiV3Key"> | |
| 39 | + <el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入API V3秘钥" clearable | |
| 40 | + :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input> | |
| 41 | + </el-form-item> | |
| 42 | + <el-form-item label-width="180px" label="apiclient_key.perm证书" prop="weChatConfig.privateKeyContent"> | |
| 43 | + <el-input v-model="form.weChatConfig.privateKeyContent" type="textarea" | |
| 44 | + placeholder="请上传apiclient_key.perm证书" | |
| 45 | + readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | |
| 46 | + </el-form-item> | |
| 47 | + <el-form-item label-width="180px" label="" prop="privateKeyContentFile"> | |
| 48 | + <el-upload ref="privateKeyContentFile" | |
| 49 | + :limit="1" | |
| 50 | + :accept="fileAccept" | |
| 51 | + :headers="header" | |
| 52 | + action="" | |
| 53 | + :before-upload="pemFileBeforeUpload" | |
| 54 | + :http-request="privateKeyUpload" | |
| 55 | + > | |
| 56 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | |
| 57 | + </el-upload> | |
| 58 | + </el-form-item> | |
| 59 | + <el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="weChatConfig.privateCertContent"> | |
| 60 | + <el-input v-model="form.weChatConfig.privateCertContent" type="textarea" | |
| 61 | + placeholder="请上传apiclient_cert.perm证书" | |
| 62 | + readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input> | |
| 63 | + </el-form-item> | |
| 64 | + <el-form-item label-width="180px" label="" prop="privateCertContentFile"> | |
| 65 | + <el-upload ref="privateCertContentFile" | |
| 66 | + :limit="1" | |
| 67 | + :accept="fileAccept" | |
| 68 | + :headers="header" | |
| 69 | + action="" | |
| 70 | + :before-upload="pemFileBeforeUpload" | |
| 71 | + :http-request="privateCertUpload" | |
| 72 | + > | |
| 73 | + <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button> | |
| 74 | + </el-upload> | |
| 75 | + </el-form-item> | |
| 76 | + </div> | |
| 77 | + <el-form-item label-width="180px" label="备注" prop="remark"> | |
| 78 | + <el-input v-model="form.remark" :style="{width: '100%'}"></el-input> | |
| 79 | + </el-form-item> | |
| 80 | + </el-form> | |
| 81 | + <div slot="footer" class="dialog-footer"> | |
| 82 | + <el-button @click="close">取消</el-button> | |
| 83 | + <el-button type="primary" @click="handleConfirm">确定</el-button> | |
| 84 | + </div> | |
| 85 | + </el-dialog> | |
| 86 | + </div> | |
| 87 | +</template> | |
| 88 | +<script> | |
| 89 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | |
| 90 | +import {createChannel, getChannel, updateChannel} from "@/api/pay/channel"; | |
| 91 | + | |
| 92 | +const defaultForm = { | |
| 93 | + code: '', | |
| 94 | + status: null, | |
| 95 | + remark: '', | |
| 96 | + feeRate: null, | |
| 97 | + appId: '', | |
| 98 | + merchantId: null, | |
| 99 | + weChatConfig: { | |
| 100 | + appId: '', | |
| 101 | + mchId: '', | |
| 102 | + apiVersion: '', | |
| 103 | + mchKey: '', | |
| 104 | + privateKeyContent: '', | |
| 105 | + privateCertContent: '', | |
| 106 | + apiV3Key:'', | |
| 107 | + } | |
| 108 | +} | |
| 109 | + | |
| 110 | +export default { | |
| 111 | + name: "wechatChannelForm", | |
| 112 | + components: {}, | |
| 113 | + props: { | |
| 114 | + // 传输的参数 | |
| 115 | + transferParam: { | |
| 116 | + // 加载动画 | |
| 117 | + "loading": false, | |
| 118 | + // 是否修改 | |
| 119 | + "edit": false, | |
| 120 | + // 是否显示 | |
| 121 | + "wechatOpen": false, | |
| 122 | + // 应用ID | |
| 123 | + "appId": null, | |
| 124 | + // 渠道编码 | |
| 125 | + "payCode": null, | |
| 126 | + // 商户对象 | |
| 127 | + "payMerchant": { | |
| 128 | + // 编号 | |
| 129 | + "id": null, | |
| 130 | + // 名称 | |
| 131 | + "name": null | |
| 132 | + }, | |
| 133 | + } | |
| 134 | + }, | |
| 135 | + data() { | |
| 136 | + return { | |
| 137 | + title:'', | |
| 138 | + form: JSON.parse(JSON.stringify(defaultForm)), | |
| 139 | + rules: { | |
| 140 | + feeRate: [{ | |
| 141 | + required: true, | |
| 142 | + message: '请输入渠道费率', | |
| 143 | + trigger: 'blur' | |
| 144 | + }], | |
| 145 | + 'weChatConfig.mchId': [{ | |
| 146 | + required: true, | |
| 147 | + message: '请传入商户号', | |
| 148 | + trigger: 'blur' | |
| 149 | + }], | |
| 150 | + 'weChatConfig.appId': [{ | |
| 151 | + required: true, | |
| 152 | + message: '请输入公众号APPID', | |
| 153 | + trigger: 'blur' | |
| 154 | + }], | |
| 155 | + status: [{ | |
| 156 | + required: true, | |
| 157 | + message: '渠道状态不能为空', | |
| 158 | + trigger: 'blur' | |
| 159 | + }], | |
| 160 | + 'weChatConfig.apiVersion': [{ | |
| 161 | + required: true, | |
| 162 | + message: 'API版本不能为空', | |
| 163 | + trigger: 'blur' | |
| 164 | + }], | |
| 165 | + 'weChatConfig.mchKey': [{ | |
| 166 | + required: true, | |
| 167 | + message: '请输入商户秘钥', | |
| 168 | + trigger: 'blur' | |
| 169 | + }], | |
| 170 | + 'weChatConfig.privateKeyContent': [{ | |
| 171 | + required: true, | |
| 172 | + message: '请上传apiclient_key.perm证书', | |
| 173 | + trigger: 'blur' | |
| 174 | + }], | |
| 175 | + 'weChatConfig.privateCertContent': [{ | |
| 176 | + required: true, | |
| 177 | + message: '请上传apiclient_cert.perm证书', | |
| 178 | + trigger: 'blur' | |
| 179 | + }], | |
| 180 | + 'weChatConfig.apiV3Key': [{ | |
| 181 | + required: true, | |
| 182 | + message: '请上传apiV3秘钥值', | |
| 183 | + trigger: 'blur' | |
| 184 | + }], | |
| 185 | + }, | |
| 186 | + // 文件上传的header | |
| 187 | + header: { | |
| 188 | + "Authorization": null | |
| 189 | + }, | |
| 190 | + fileAccept: ".pem", | |
| 191 | + // 渠道状态 数据字典 | |
| 192 | + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS), | |
| 193 | + versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION), | |
| 194 | + } | |
| 195 | + }, | |
| 196 | + watch: { | |
| 197 | + transferParam: { | |
| 198 | + deep: true, // 深度监听 | |
| 199 | + handler(newVal) { | |
| 200 | + if (newVal.wechatOpen) { | |
| 201 | + this.form.code = newVal.payCode; | |
| 202 | + this.form.appId = newVal.appId; | |
| 203 | + this.form.merchantId = newVal.payMerchant.id; | |
| 204 | + // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据 | |
| 205 | + if (newVal.edit && newVal.loading) { | |
| 206 | + this.title = "编辑支付渠道"; | |
| 207 | + this.init(); | |
| 208 | + } else { | |
| 209 | + this.title = "创建支付渠道"; | |
| 210 | + } | |
| 211 | + } | |
| 212 | + } | |
| 213 | + } | |
| 214 | + }, | |
| 215 | + methods: { | |
| 216 | + init() { | |
| 217 | + getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode) | |
| 218 | + .then(response => { | |
| 219 | + this.form.id = response.data.id; | |
| 220 | + this.form.feeRate = response.data.feeRate; | |
| 221 | + this.form.appId = response.data.appId; | |
| 222 | + this.form.status = response.data.status; | |
| 223 | + this.form.remark = response.data.remark; | |
| 224 | + | |
| 225 | + let config = JSON.parse(response.data.config); | |
| 226 | + this.form.weChatConfig.appId = config.appId; | |
| 227 | + this.form.weChatConfig.apiVersion = config.apiVersion; | |
| 228 | + this.form.weChatConfig.mchId = config.mchId; | |
| 229 | + this.form.weChatConfig.mchKey = config.mchKey; | |
| 230 | + this.form.weChatConfig.privateKeyContent = config.privateKeyContent; | |
| 231 | + this.form.weChatConfig.privateCertContent = config.privateCertContent; | |
| 232 | + this.form.weChatConfig.apiV3Key = config.apiV3Key; | |
| 233 | + this.transferParam.loading = false; | |
| 234 | + }) | |
| 235 | + }, | |
| 236 | + close() { | |
| 237 | + this.transferParam.wechatOpen = false; | |
| 238 | + this.form = JSON.parse(JSON.stringify(defaultForm)); | |
| 239 | + }, | |
| 240 | + handleConfirm() { | |
| 241 | + this.$refs['wechatJsApiForm'].validate(valid => { | |
| 242 | + if (!valid) { | |
| 243 | + return | |
| 244 | + } | |
| 245 | + let data = this.form; | |
| 246 | + data.config = JSON.stringify(this.form.weChatConfig); | |
| 247 | + if (this.transferParam.edit) { | |
| 248 | + updateChannel(data).then(response => { | |
| 249 | + if (response.code === 0) { | |
| 250 | + this.msgSuccess("修改成功"); | |
| 251 | + this.close(); | |
| 252 | + } | |
| 253 | + | |
| 254 | + }) | |
| 255 | + } else { | |
| 256 | + | |
| 257 | + createChannel(data).then(response => { | |
| 258 | + if (response.code === 0) { | |
| 259 | + this.msgSuccess("新增成功"); | |
| 260 | + this.$parent.refreshTable(); | |
| 261 | + this.close(); | |
| 262 | + } | |
| 263 | + }); | |
| 264 | + } | |
| 265 | + }); | |
| 266 | + }, | |
| 267 | + pemFileBeforeUpload(file) { | |
| 268 | + let format = '.' + file.name.split(".")[1]; | |
| 269 | + if (format !== this.fileAccept) { | |
| 270 | + this.$message.error('请上传指定格式"' + this.fileAccept + '"文件'); | |
| 271 | + return false; | |
| 272 | + } | |
| 273 | + let isRightSize = file.size / 1024 / 1024 < 2 | |
| 274 | + if (!isRightSize) { | |
| 275 | + this.$message.error('文件大小超过 2MB') | |
| 276 | + } | |
| 277 | + return isRightSize | |
| 278 | + }, | |
| 279 | + privateKeyUpload(event) { | |
| 280 | + const readFile = new FileReader() | |
| 281 | + readFile.onload = (e) => { | |
| 282 | + this.form.weChatConfig.privateKeyContent = e.target.result | |
| 283 | + } | |
| 284 | + readFile.readAsText(event.file); | |
| 285 | + }, | |
| 286 | + privateCertUpload(event) { | |
| 287 | + const readFile = new FileReader() | |
| 288 | + readFile.onload = (e) => { | |
| 289 | + this.form.weChatConfig.privateCertContent = e.target.result | |
| 290 | + } | |
| 291 | + readFile.readAsText(event.file); | |
| 292 | + } | |
| 293 | + } | |
| 294 | +} | |
| 295 | + | |
| 296 | +</script> | |
| 297 | +<style scoped> | |
| 298 | + | |
| 299 | +</style> | ... | ... |
yudao-admin-ui/src/views/pay/app/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="app-container"> | |
| 3 | + | |
| 4 | + <!-- 搜索工作栏 --> | |
| 5 | + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px"> | |
| 6 | + <el-form-item label="应用名" prop="name"> | |
| 7 | + <el-input v-model="queryParams.name" placeholder="请输入应用名" clearable size="small" | |
| 8 | + @keyup.enter.native="handleQuery"/> | |
| 9 | + </el-form-item> | |
| 10 | + <el-form-item label="商户名称" prop="merchantName"> | |
| 11 | + <el-input v-model="queryParams.merchantName" placeholder="请输入商户名称" clearable size="small" | |
| 12 | + @keyup.enter.native="handleQuery"/> | |
| 13 | + </el-form-item> | |
| 14 | + <el-form-item label="开启状态" prop="status"> | |
| 15 | + <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable size="small"> | |
| 16 | + <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" | |
| 17 | + :value="parseInt(dict.value)"/> | |
| 18 | + </el-select> | |
| 19 | + </el-form-item> | |
| 20 | + <el-form-item> | |
| 21 | + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> | |
| 22 | + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> | |
| 23 | + </el-form-item> | |
| 24 | + </el-form> | |
| 25 | + | |
| 26 | + <!-- 操作工具栏 --> | |
| 27 | + <el-row :gutter="10" class="mb8"> | |
| 28 | + <el-col :span="1.5"> | |
| 29 | + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" | |
| 30 | + v-hasPermi="['pay:app:create']">新增 | |
| 31 | + </el-button> | |
| 32 | + </el-col> | |
| 33 | + <el-col :span="1.5"> | |
| 34 | + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" | |
| 35 | + v-hasPermi="['pay:app:export']">导出 | |
| 36 | + </el-button> | |
| 37 | + </el-col> | |
| 38 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | |
| 39 | + </el-row> | |
| 40 | + | |
| 41 | + <!-- 列表 --> | |
| 42 | + <el-table v-loading="loading" :data="list"> | |
| 43 | + <el-table-column label="应用编号" align="center" prop="id"/> | |
| 44 | + <el-table-column label="应用名" align="center" prop="name"/> | |
| 45 | + <el-table-column label="开启状态" align="center" prop="status"> | |
| 46 | + <template slot-scope="scope"> | |
| 47 | + <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" | |
| 48 | + @change="handleStatusChange(scope.row)"/> | |
| 49 | + </template> | |
| 50 | + </el-table-column> | |
| 51 | + <el-table-column label="商户名称" align="center" prop="payMerchant.name"/> | |
| 52 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | |
| 53 | + <template slot-scope="scope"> | |
| 54 | + <span>{{ parseTime(scope.row.createTime) }}</span> | |
| 55 | + </template> | |
| 56 | + </el-table-column> | |
| 57 | + <el-table-column label="支付宝配置" align="center"> | |
| 58 | + <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center"> | |
| 59 | + <template slot-scope="scope"> | |
| 60 | + <el-button type="success" icon="el-icon-check" circle | |
| 61 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)" | |
| 62 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"> | |
| 63 | + </el-button> | |
| 64 | + <el-button v-else | |
| 65 | + type="danger" icon="el-icon-close" circle | |
| 66 | + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"> | |
| 67 | + </el-button> | |
| 68 | + </template> | |
| 69 | + </el-table-column> | |
| 70 | + <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center"> | |
| 71 | + <template slot-scope="scope"> | |
| 72 | + <el-button type="success" icon="el-icon-check" circle | |
| 73 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)" | |
| 74 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"> | |
| 75 | + </el-button> | |
| 76 | + <el-button v-else | |
| 77 | + type="danger" icon="el-icon-close" circle | |
| 78 | + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)"> | |
| 79 | + </el-button> | |
| 80 | + </template> | |
| 81 | + </el-table-column> | |
| 82 | + <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center"> | |
| 83 | + <template slot-scope="scope"> | |
| 84 | + <el-button type="success" icon="el-icon-check" circle | |
| 85 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)" | |
| 86 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"> | |
| 87 | + </el-button> | |
| 88 | + <el-button v-else | |
| 89 | + type="danger" icon="el-icon-close" circle | |
| 90 | + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)"> | |
| 91 | + </el-button> | |
| 92 | + </template> | |
| 93 | + </el-table-column> | |
| 94 | + <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center"> | |
| 95 | + <template slot-scope="scope"> | |
| 96 | + <el-button type="success" icon="el-icon-check" circle | |
| 97 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)" | |
| 98 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"> | |
| 99 | + </el-button> | |
| 100 | + <el-button v-else | |
| 101 | + type="danger" icon="el-icon-close" circle | |
| 102 | + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)"> | |
| 103 | + </el-button> | |
| 104 | + </template> | |
| 105 | + </el-table-column> | |
| 106 | + </el-table-column> | |
| 107 | + <el-table-column label="微信配置" align="center"> | |
| 108 | + <el-table-column :label="payChannelEnum.WX_LITE.name" align="center"> | |
| 109 | + <template slot-scope="scope"> | |
| 110 | + <el-button type="success" icon="el-icon-check" circle | |
| 111 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)" | |
| 112 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)"> | |
| 113 | + </el-button> | |
| 114 | + <el-button v-else | |
| 115 | + type="danger" icon="el-icon-close" circle | |
| 116 | + @click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)"> | |
| 117 | + </el-button> | |
| 118 | + </template> | |
| 119 | + </el-table-column> | |
| 120 | + <el-table-column :label="payChannelEnum.WX_PUB.name" align="center"> | |
| 121 | + <template slot-scope="scope"> | |
| 122 | + <el-button type="success" icon="el-icon-check" circle | |
| 123 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)" | |
| 124 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)"> | |
| 125 | + </el-button> | |
| 126 | + <el-button v-else | |
| 127 | + type="danger" icon="el-icon-close" circle | |
| 128 | + @click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)"> | |
| 129 | + </el-button> | |
| 130 | + </template> | |
| 131 | + </el-table-column> | |
| 132 | + <el-table-column :label="payChannelEnum.WX_APP.name" align="center"> | |
| 133 | + <template slot-scope="scope"> | |
| 134 | + <el-button type="success" icon="el-icon-check" circle | |
| 135 | + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)" | |
| 136 | + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)"> | |
| 137 | + </el-button> | |
| 138 | + <el-button v-else | |
| 139 | + type="danger" icon="el-icon-close" circle | |
| 140 | + @click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)"> | |
| 141 | + </el-button> | |
| 142 | + </template> | |
| 143 | + </el-table-column> | |
| 144 | + </el-table-column> | |
| 145 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | |
| 146 | + <template slot-scope="scope"> | |
| 147 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | |
| 148 | + v-hasPermi="['pay:app:update']">修改 | |
| 149 | + </el-button> | |
| 150 | + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | |
| 151 | + v-hasPermi="['pay:app:delete']">删除 | |
| 152 | + </el-button> | |
| 153 | + </template> | |
| 154 | + </el-table-column> | |
| 155 | + </el-table> | |
| 156 | + <!-- 分页组件 --> | |
| 157 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | |
| 158 | + @pagination="getList"/> | |
| 159 | + | |
| 160 | + <!-- 对话框(添加 / 修改) --> | |
| 161 | + <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> | |
| 162 | + <el-form ref="form" :model="form" :rules="rules" label-width="160px"> | |
| 163 | + <el-form-item label="应用名" prop="name"> | |
| 164 | + <el-input v-model="form.name" placeholder="请输入应用名"/> | |
| 165 | + </el-form-item> | |
| 166 | + <el-form-item label="所属商户" prop="merchantId"> | |
| 167 | + <el-select | |
| 168 | + v-model="form.merchantId" | |
| 169 | + filterable | |
| 170 | + remote | |
| 171 | + reserve-keyword | |
| 172 | + placeholder="请选择所属商户" | |
| 173 | + :remote-method="handleGetMerchantListByName" | |
| 174 | + :loading="loading"> | |
| 175 | + <el-option | |
| 176 | + v-for="item in merchantList" | |
| 177 | + :key="item.id" | |
| 178 | + :label="item.name" | |
| 179 | + :value="item.id"> | |
| 180 | + </el-option> | |
| 181 | + </el-select> | |
| 182 | + </el-form-item> | |
| 183 | + <el-form-item label="开启状态" prop="status"> | |
| 184 | + <el-radio-group v-model="form.status"> | |
| 185 | + <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | |
| 186 | + {{ dict.label }} | |
| 187 | + </el-radio> | |
| 188 | + </el-radio-group> | |
| 189 | + </el-form-item> | |
| 190 | + | |
| 191 | + <el-form-item label="支付结果的回调地址" prop="payNotifyUrl"> | |
| 192 | + <el-input v-model="form.payNotifyUrl" placeholder="请输入支付结果的回调地址"/> | |
| 193 | + </el-form-item> | |
| 194 | + <el-form-item label="退款结果的回调地址" prop="refundNotifyUrl"> | |
| 195 | + <el-input v-model="form.refundNotifyUrl" placeholder="请输入退款结果的回调地址"/> | |
| 196 | + </el-form-item> | |
| 197 | + | |
| 198 | + <el-form-item label="备注" prop="remark"> | |
| 199 | + <el-input v-model="form.remark" placeholder="请输入备注"/> | |
| 200 | + </el-form-item> | |
| 201 | + </el-form> | |
| 202 | + <div slot="footer" class="dialog-footer"> | |
| 203 | + <el-button type="primary" @click="submitForm">确 定</el-button> | |
| 204 | + <el-button @click="cancel">取 消</el-button> | |
| 205 | + </div> | |
| 206 | + </el-dialog> | |
| 207 | + <wechat-channel-form :transferParam="channelParam"></wechat-channel-form> | |
| 208 | + <ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form> | |
| 209 | + </div> | |
| 210 | +</template> | |
| 211 | + | |
| 212 | +<script> | |
| 213 | +import {createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage, exportAppExcel} from "@/api/pay/app"; | |
| 214 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | |
| 215 | +import {PayType, PayChannelEnum, SysCommonStatusEnum} from "@/utils/constants"; | |
| 216 | +import {getMerchantListByName} from "@/api/pay/merchant"; | |
| 217 | +import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm"; | |
| 218 | +import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm"; | |
| 219 | + | |
| 220 | +export default { | |
| 221 | + name: "App", | |
| 222 | + components: { | |
| 223 | + "wechatChannelForm": wechatChannelForm, | |
| 224 | + "aliPayChannelForm": aliPayChannelForm | |
| 225 | + }, | |
| 226 | + data() { | |
| 227 | + return { | |
| 228 | + // 遮罩层 | |
| 229 | + loading: true, | |
| 230 | + // 显示搜索条件 | |
| 231 | + showSearch: true, | |
| 232 | + // 总条数 | |
| 233 | + total: 0, | |
| 234 | + // 支付应用信息列表 | |
| 235 | + list: [], | |
| 236 | + // 弹出层标题 | |
| 237 | + title: "", | |
| 238 | + // 是否显示弹出层 | |
| 239 | + open: false, | |
| 240 | + dateRangeCreateTime: [], | |
| 241 | + // 查询参数 | |
| 242 | + queryParams: { | |
| 243 | + pageNo: 1, | |
| 244 | + pageSize: 10, | |
| 245 | + name: null, | |
| 246 | + status: null, | |
| 247 | + remark: null, | |
| 248 | + payNotifyUrl: null, | |
| 249 | + refundNotifyUrl: null, | |
| 250 | + merchantName: null, | |
| 251 | + }, | |
| 252 | + // 表单参数 | |
| 253 | + form: {}, | |
| 254 | + // 表单校验 | |
| 255 | + rules: { | |
| 256 | + name: [{required: true, message: "应用名不能为空", trigger: "blur"}], | |
| 257 | + status: [{required: true, message: "开启状态不能为空", trigger: "blur"}], | |
| 258 | + payNotifyUrl: [{required: true, message: "支付结果的回调地址不能为空", trigger: "blur"}], | |
| 259 | + refundNotifyUrl: [{required: true, message: "退款结果的回调地址不能为空", trigger: "blur"}], | |
| 260 | + merchantId: [{required: true, message: "商户编号不能为空", trigger: "blur"}], | |
| 261 | + }, | |
| 262 | + // 数据字典 | |
| 263 | + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS), | |
| 264 | + sysCommonStatusEnum: SysCommonStatusEnum, | |
| 265 | + // 支付渠道枚举 | |
| 266 | + payChannelEnum: PayChannelEnum, | |
| 267 | + // 支付类型 | |
| 268 | + payType: PayType, | |
| 269 | + // 商户列表 | |
| 270 | + merchantList: [], | |
| 271 | + // 是否显示支付窗口 | |
| 272 | + payOpen: false, | |
| 273 | + // 微信组件传参参数 | |
| 274 | + channelParam: { | |
| 275 | + // 是否修改 | |
| 276 | + "edit": false, | |
| 277 | + // 微信是否显示 | |
| 278 | + "wechatOpen": false, | |
| 279 | + // 支付宝是否显示 | |
| 280 | + "aliPayOpen": false, | |
| 281 | + // 应用ID | |
| 282 | + "appId": null, | |
| 283 | + // 渠道编码 | |
| 284 | + "payCode": null, | |
| 285 | + // 商户对象 | |
| 286 | + "payMerchant": { | |
| 287 | + // 编号 | |
| 288 | + "id": null, | |
| 289 | + // 名称 | |
| 290 | + "name": null | |
| 291 | + }, | |
| 292 | + } | |
| 293 | + }; | |
| 294 | + }, | |
| 295 | + created() { | |
| 296 | + this.getList(); | |
| 297 | + this.handleGetMerchantListByName(null); | |
| 298 | + }, | |
| 299 | + methods: { | |
| 300 | + /** 查询列表 */ | |
| 301 | + getList() { | |
| 302 | + this.loading = true; | |
| 303 | + // 处理查询参数 | |
| 304 | + let params = {...this.queryParams}; | |
| 305 | + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 306 | + // 执行查询 | |
| 307 | + getAppPage(params).then(response => { | |
| 308 | + this.list = response.data.list; | |
| 309 | + console.log(this.list); | |
| 310 | + this.total = response.data.total; | |
| 311 | + this.loading = false; | |
| 312 | + }); | |
| 313 | + }, | |
| 314 | + /** 取消按钮 */ | |
| 315 | + cancel() { | |
| 316 | + this.open = false; | |
| 317 | + this.reset(); | |
| 318 | + }, | |
| 319 | + /** 表单重置 */ | |
| 320 | + reset() { | |
| 321 | + this.form = { | |
| 322 | + id: undefined, | |
| 323 | + name: undefined, | |
| 324 | + status: undefined, | |
| 325 | + remark: undefined, | |
| 326 | + payNotifyUrl: undefined, | |
| 327 | + refundNotifyUrl: undefined, | |
| 328 | + merchantId: undefined, | |
| 329 | + }; | |
| 330 | + this.resetForm("form"); | |
| 331 | + }, | |
| 332 | + /** 搜索按钮操作 */ | |
| 333 | + handleQuery() { | |
| 334 | + this.queryParams.pageNo = 1; | |
| 335 | + this.getList(); | |
| 336 | + }, | |
| 337 | + /** 重置按钮操作 */ | |
| 338 | + resetQuery() { | |
| 339 | + this.dateRangeCreateTime = []; | |
| 340 | + this.resetForm("queryForm"); | |
| 341 | + this.handleQuery(); | |
| 342 | + }, | |
| 343 | + /** 新增按钮操作 */ | |
| 344 | + handleAdd() { | |
| 345 | + this.reset(); | |
| 346 | + this.open = true; | |
| 347 | + this.title = "添加支付应用信息"; | |
| 348 | + }, | |
| 349 | + /** 修改按钮操作 */ | |
| 350 | + handleUpdate(row) { | |
| 351 | + this.reset(); | |
| 352 | + const id = row.id; | |
| 353 | + getApp(id).then(response => { | |
| 354 | + this.form = response.data; | |
| 355 | + this.open = true; | |
| 356 | + this.title = "修改支付应用信息"; | |
| 357 | + }); | |
| 358 | + }, | |
| 359 | + // 用户状态修改 | |
| 360 | + handleStatusChange(row) { | |
| 361 | + let text = row.status === SysCommonStatusEnum.ENABLE ? "启用" : "停用"; | |
| 362 | + this.$confirm('确认要"' + text + '""' + row.name + '"应用吗?', "警告", { | |
| 363 | + confirmButtonText: "确定", | |
| 364 | + cancelButtonText: "取消", | |
| 365 | + type: "warning" | |
| 366 | + }).then(function () { | |
| 367 | + return changeAppStatus(row.id, row.status); | |
| 368 | + }).then(() => { | |
| 369 | + this.msgSuccess(text + "成功"); | |
| 370 | + }).catch(function () { | |
| 371 | + row.status = row.status === SysCommonStatusEnum.ENABLE ? SysCommonStatusEnum.DISABLE | |
| 372 | + : SysCommonStatusEnum.ENABLE; | |
| 373 | + }); | |
| 374 | + }, | |
| 375 | + /** 提交按钮 */ | |
| 376 | + submitForm() { | |
| 377 | + this.$refs["form"].validate(valid => { | |
| 378 | + if (!valid) { | |
| 379 | + return; | |
| 380 | + } | |
| 381 | + // 修改的提交 | |
| 382 | + if (this.form.id != null) { | |
| 383 | + updateApp(this.form).then(response => { | |
| 384 | + this.msgSuccess("修改成功"); | |
| 385 | + this.open = false; | |
| 386 | + this.getList(); | |
| 387 | + }); | |
| 388 | + return; | |
| 389 | + } | |
| 390 | + // 添加的提交 | |
| 391 | + createApp(this.form).then(response => { | |
| 392 | + this.msgSuccess("新增成功"); | |
| 393 | + this.open = false; | |
| 394 | + this.getList(); | |
| 395 | + }); | |
| 396 | + }); | |
| 397 | + }, | |
| 398 | + /** 删除按钮操作 */ | |
| 399 | + handleDelete(row) { | |
| 400 | + const id = row.id; | |
| 401 | + this.$confirm('是否确认删除支付应用信息编号为"' + id + '"的数据项?', "警告", { | |
| 402 | + confirmButtonText: "确定", | |
| 403 | + cancelButtonText: "取消", | |
| 404 | + type: "warning" | |
| 405 | + }).then(function () { | |
| 406 | + return deleteApp(id); | |
| 407 | + }).then(() => { | |
| 408 | + this.getList(); | |
| 409 | + this.msgSuccess("删除成功"); | |
| 410 | + }).catch(() => { | |
| 411 | + this.$message({ | |
| 412 | + type: 'info', | |
| 413 | + message: '已取消删除' | |
| 414 | + }); | |
| 415 | + }); | |
| 416 | + }, | |
| 417 | + /** 导出按钮操作 */ | |
| 418 | + handleExport() { | |
| 419 | + // 处理查询参数 | |
| 420 | + let params = {...this.queryParams}; | |
| 421 | + params.pageNo = undefined; | |
| 422 | + params.pageSize = undefined; | |
| 423 | + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 424 | + // 执行导出 | |
| 425 | + this.$confirm('是否确认导出所有支付应用信息数据项?', "警告", { | |
| 426 | + confirmButtonText: "确定", | |
| 427 | + cancelButtonText: "取消", | |
| 428 | + type: "warning" | |
| 429 | + }).then(function () { | |
| 430 | + return exportAppExcel(params); | |
| 431 | + }).then(response => { | |
| 432 | + this.downloadExcel(response, '支付应用信息.xls'); | |
| 433 | + }) | |
| 434 | + }, | |
| 435 | + /** | |
| 436 | + * 根据商户名称模糊匹配商户信息 | |
| 437 | + * @param name 商户名称 | |
| 438 | + */ | |
| 439 | + handleGetMerchantListByName(name) { | |
| 440 | + getMerchantListByName(name).then(response => { | |
| 441 | + this.merchantList = response.data; | |
| 442 | + }); | |
| 443 | + }, | |
| 444 | + /** | |
| 445 | + * 修改支付渠道信息 | |
| 446 | + */ | |
| 447 | + handleUpdateChannel(row, payCode, type) { | |
| 448 | + this.settingChannelParam(row, payCode, type) | |
| 449 | + this.channelParam.edit = true; | |
| 450 | + this.channelParam.loading = true; | |
| 451 | + | |
| 452 | + }, | |
| 453 | + /** | |
| 454 | + * 新增支付渠道信息 | |
| 455 | + */ | |
| 456 | + handleCreateChannel(row, payCode, type) { | |
| 457 | + this.settingChannelParam(row, payCode, type) | |
| 458 | + this.channelParam.edit = false; | |
| 459 | + this.channelParam.loading = false; | |
| 460 | + }, | |
| 461 | + /** | |
| 462 | + * 设置支付渠道信息 | |
| 463 | + */ | |
| 464 | + settingChannelParam(row, payCode, type) { | |
| 465 | + if (type === PayType.WECHAT) { | |
| 466 | + this.channelParam.wechatOpen = true; | |
| 467 | + this.channelParam.aliPayOpen = false; | |
| 468 | + } | |
| 469 | + if (type === PayType.ALIPAY) { | |
| 470 | + this.channelParam.aliPayOpen = true; | |
| 471 | + this.channelParam.wechatOpen = false; | |
| 472 | + } | |
| 473 | + this.channelParam.edit = false; | |
| 474 | + this.channelParam.loading = false; | |
| 475 | + this.channelParam.appId = row.id; | |
| 476 | + this.channelParam.payCode = payCode; | |
| 477 | + this.channelParam.payMerchant = row.payMerchant; | |
| 478 | + }, | |
| 479 | + /** | |
| 480 | + * 根据渠道编码判断渠道列表中是否存在 | |
| 481 | + * @param channels 渠道列表 | |
| 482 | + * @param channelCode 渠道编码 | |
| 483 | + */ | |
| 484 | + judgeChannelExist(channels, channelCode) { | |
| 485 | + return channels.indexOf(channelCode) !== -1; | |
| 486 | + }, | |
| 487 | + refreshTable() { | |
| 488 | + this.getList(); | |
| 489 | + } | |
| 490 | + } | |
| 491 | +}; | |
| 492 | +</script> | ... | ... |
yudao-admin-ui/src/views/pay/merchant/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="app-container"> | |
| 3 | + | |
| 4 | + <!-- 搜索工作栏 --> | |
| 5 | + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px"> | |
| 6 | + <el-form-item label="商户号" prop="no"> | |
| 7 | + <el-input v-model="queryParams.no" placeholder="请输入商户号" clearable size="small" @keyup.enter.native="handleQuery"/> | |
| 8 | + </el-form-item> | |
| 9 | + <el-form-item label="商户全称" prop="name"> | |
| 10 | + <el-input v-model="queryParams.name" placeholder="请输入商户全称" clearable size="small" @keyup.enter.native="handleQuery"/> | |
| 11 | + </el-form-item> | |
| 12 | + <el-form-item label="商户简称" prop="shortName"> | |
| 13 | + <el-input v-model="queryParams.shortName" placeholder="请输入商户简称" clearable size="small" @keyup.enter.native="handleQuery"/> | |
| 14 | + </el-form-item> | |
| 15 | + <el-form-item label="开启状态" prop="status"> | |
| 16 | + <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable size="small"> | |
| 17 | + <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/> | |
| 18 | + </el-select> | |
| 19 | + </el-form-item> | |
| 20 | + <el-form-item label="备注" prop="remark"> | |
| 21 | + <el-input v-model="queryParams.remark" placeholder="请输入备注" clearable size="small" @keyup.enter.native="handleQuery"/> | |
| 22 | + </el-form-item> | |
| 23 | + <el-form-item label="创建时间"> | |
| 24 | + <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd" | |
| 25 | + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" /> | |
| 26 | + </el-form-item> | |
| 27 | + <el-form-item> | |
| 28 | + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> | |
| 29 | + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> | |
| 30 | + </el-form-item> | |
| 31 | + </el-form> | |
| 32 | + | |
| 33 | + <!-- 操作工具栏 --> | |
| 34 | + <el-row :gutter="10" class="mb8"> | |
| 35 | + <el-col :span="1.5"> | |
| 36 | + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" | |
| 37 | + v-hasPermi="['pay:merchant:create']">新增</el-button> | |
| 38 | + </el-col> | |
| 39 | + <el-col :span="1.5"> | |
| 40 | + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" | |
| 41 | + v-hasPermi="['pay:merchant:export']">导出</el-button> | |
| 42 | + </el-col> | |
| 43 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | |
| 44 | + </el-row> | |
| 45 | + | |
| 46 | + <!-- 列表 --> | |
| 47 | + <el-table v-loading="loading" :data="list"> | |
| 48 | + <el-table-column label="商户编号" align="center" prop="id" /> | |
| 49 | + <el-table-column label="商户号" align="center" prop="no" /> | |
| 50 | + <el-table-column label="商户全称" align="center" prop="name" /> | |
| 51 | + <el-table-column label="商户简称" align="center" prop="shortName" /> | |
| 52 | + <el-table-column label="开启状态" align="center" prop="status" > | |
| 53 | + <template slot-scope="scope"> | |
| 54 | + <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)" /> | |
| 55 | + </template> | |
| 56 | + </el-table-column> | |
| 57 | + <el-table-column label="备注" align="center" prop="remark" /> | |
| 58 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | |
| 59 | + <template slot-scope="scope"> | |
| 60 | + <span>{{ parseTime(scope.row.createTime) }}</span> | |
| 61 | + </template> | |
| 62 | + </el-table-column> | |
| 63 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | |
| 64 | + <template slot-scope="scope"> | |
| 65 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | |
| 66 | + v-hasPermi="['pay:merchant:update']">修改</el-button> | |
| 67 | + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | |
| 68 | + v-hasPermi="['pay:merchant:delete']">删除</el-button> | |
| 69 | + </template> | |
| 70 | + </el-table-column> | |
| 71 | + </el-table> | |
| 72 | + <!-- 分页组件 --> | |
| 73 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | |
| 74 | + @pagination="getList"/> | |
| 75 | + | |
| 76 | + <!-- 对话框(添加 / 修改) --> | |
| 77 | + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> | |
| 78 | + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> | |
| 79 | +<!-- <el-form-item label="商户号" prop="no">--> | |
| 80 | +<!-- <el-input v-model="form.no" placeholder="请输入商户号" />--> | |
| 81 | +<!-- </el-form-item>--> | |
| 82 | + <el-form-item label="商户全称" prop="name"> | |
| 83 | + <el-input v-model="form.name" placeholder="请输入商户全称" /> | |
| 84 | + </el-form-item> | |
| 85 | + <el-form-item label="商户简称" prop="shortName"> | |
| 86 | + <el-input v-model="form.shortName" placeholder="请输入商户简称" /> | |
| 87 | + </el-form-item> | |
| 88 | + <el-form-item label="开启状态" prop="status"> | |
| 89 | + <el-radio-group v-model="form.status"> | |
| 90 | + <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)"> | |
| 91 | + {{dict.label}}</el-radio> | |
| 92 | + </el-radio-group> | |
| 93 | + </el-form-item> | |
| 94 | + <el-form-item label="备注" prop="remark"> | |
| 95 | + <el-input v-model="form.remark" placeholder="请输入备注" /> | |
| 96 | + </el-form-item> | |
| 97 | + </el-form> | |
| 98 | + <div slot="footer" class="dialog-footer"> | |
| 99 | + <el-button type="primary" @click="submitForm">确 定</el-button> | |
| 100 | + <el-button @click="cancel">取 消</el-button> | |
| 101 | + </div> | |
| 102 | + </el-dialog> | |
| 103 | + </div> | |
| 104 | +</template> | |
| 105 | + | |
| 106 | +<script> | |
| 107 | +import { | |
| 108 | + createMerchant, | |
| 109 | + updateMerchant, | |
| 110 | + changeMerchantStatus, | |
| 111 | + deleteMerchant, | |
| 112 | + getMerchant, | |
| 113 | + getMerchantPage, | |
| 114 | + exportMerchantExcel | |
| 115 | +} from "@/api/pay/merchant"; | |
| 116 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | |
| 117 | +import {SysCommonStatusEnum} from "@/utils/constants"; | |
| 118 | + | |
| 119 | +export default { | |
| 120 | + name: "Merchant", | |
| 121 | + components: { | |
| 122 | + }, | |
| 123 | + data() { | |
| 124 | + return { | |
| 125 | + // 遮罩层 | |
| 126 | + loading: true, | |
| 127 | + // 显示搜索条件 | |
| 128 | + showSearch: true, | |
| 129 | + // 总条数 | |
| 130 | + total: 0, | |
| 131 | + // 支付商户信息列表 | |
| 132 | + list: [], | |
| 133 | + // 弹出层标题 | |
| 134 | + title: "", | |
| 135 | + // 是否显示弹出层 | |
| 136 | + open: false, | |
| 137 | + dateRangeCreateTime: [], | |
| 138 | + // 查询参数 | |
| 139 | + queryParams: { | |
| 140 | + pageNo: 1, | |
| 141 | + pageSize: 10, | |
| 142 | + no: null, | |
| 143 | + name: null, | |
| 144 | + shortName: null, | |
| 145 | + status: null, | |
| 146 | + remark: null, | |
| 147 | + }, | |
| 148 | + // 表单参数 | |
| 149 | + form: {}, | |
| 150 | + // 表单校验 | |
| 151 | + rules: { | |
| 152 | + no: [{ required: true, message: "商户号不能为空", trigger: "blur" }], | |
| 153 | + name: [{ required: true, message: "商户全称不能为空", trigger: "blur" }], | |
| 154 | + shortName: [{ required: true, message: "商户简称不能为空", trigger: "blur" }], | |
| 155 | + status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }], | |
| 156 | + }, | |
| 157 | + // 商户状态数据字典 | |
| 158 | + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS) | |
| 159 | + }; | |
| 160 | + }, | |
| 161 | + created() { | |
| 162 | + this.getList(); | |
| 163 | + }, | |
| 164 | + methods: { | |
| 165 | + /** 查询列表 */ | |
| 166 | + getList() { | |
| 167 | + this.loading = true; | |
| 168 | + // 处理查询参数 | |
| 169 | + let params = {...this.queryParams}; | |
| 170 | + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 171 | + // 执行查询 | |
| 172 | + getMerchantPage(params).then(response => { | |
| 173 | + console.log(response.data); | |
| 174 | + this.list = response.data.list; | |
| 175 | + this.total = response.data.total; | |
| 176 | + this.loading = false; | |
| 177 | + }); | |
| 178 | + }, | |
| 179 | + /** 取消按钮 */ | |
| 180 | + cancel() { | |
| 181 | + this.open = false; | |
| 182 | + this.reset(); | |
| 183 | + }, | |
| 184 | + /** 表单重置 */ | |
| 185 | + reset() { | |
| 186 | + this.form = { | |
| 187 | + id: undefined, | |
| 188 | + no: undefined, | |
| 189 | + name: undefined, | |
| 190 | + shortName: undefined, | |
| 191 | + status: undefined, | |
| 192 | + remark: undefined, | |
| 193 | + }; | |
| 194 | + this.resetForm("form"); | |
| 195 | + }, | |
| 196 | + /** 搜索按钮操作 */ | |
| 197 | + handleQuery() { | |
| 198 | + this.queryParams.pageNo = 1; | |
| 199 | + this.getList(); | |
| 200 | + }, | |
| 201 | + /** 重置按钮操作 */ | |
| 202 | + resetQuery() { | |
| 203 | + this.dateRangeCreateTime = []; | |
| 204 | + this.resetForm("queryForm"); | |
| 205 | + this.handleQuery(); | |
| 206 | + }, | |
| 207 | + /** 新增按钮操作 */ | |
| 208 | + handleAdd() { | |
| 209 | + this.reset(); | |
| 210 | + this.open = true; | |
| 211 | + this.title = "添加支付商户信息"; | |
| 212 | + }, | |
| 213 | + /** 修改按钮操作 */ | |
| 214 | + handleUpdate(row) { | |
| 215 | + this.reset(); | |
| 216 | + const id = row.id; | |
| 217 | + getMerchant(id).then(response => { | |
| 218 | + this.form = response.data; | |
| 219 | + this.open = true; | |
| 220 | + this.title = "修改支付商户信息"; | |
| 221 | + }); | |
| 222 | + }, | |
| 223 | + // 用户状态修改 | |
| 224 | + handleStatusChange(row) { | |
| 225 | + let text = row.status === SysCommonStatusEnum.ENABLE ? "启用" : "停用"; | |
| 226 | + this.$confirm('确认要"' + text + '""' + row.name + '"商户吗?', "警告", { | |
| 227 | + confirmButtonText: "确定", | |
| 228 | + cancelButtonText: "取消", | |
| 229 | + type: "warning" | |
| 230 | + }).then(function() { | |
| 231 | + return changeMerchantStatus(row.id, row.status); | |
| 232 | + }).then(() => { | |
| 233 | + this.msgSuccess(text + "成功"); | |
| 234 | + }).catch(function() { | |
| 235 | + row.status = row.status === SysCommonStatusEnum.ENABLE ? SysCommonStatusEnum.DISABLE | |
| 236 | + : SysCommonStatusEnum.ENABLE; | |
| 237 | + }); | |
| 238 | + }, | |
| 239 | + /** 提交按钮 */ | |
| 240 | + submitForm() { | |
| 241 | + this.$refs["form"].validate(valid => { | |
| 242 | + if (!valid) { | |
| 243 | + return; | |
| 244 | + } | |
| 245 | + // 修改的提交 | |
| 246 | + if (this.form.id != null) { | |
| 247 | + updateMerchant(this.form).then(response => { | |
| 248 | + this.msgSuccess("修改成功"); | |
| 249 | + this.open = false; | |
| 250 | + this.getList(); | |
| 251 | + }); | |
| 252 | + return; | |
| 253 | + } | |
| 254 | + // 添加的提交 | |
| 255 | + createMerchant(this.form).then(response => { | |
| 256 | + this.msgSuccess("新增成功"); | |
| 257 | + this.open = false; | |
| 258 | + this.getList(); | |
| 259 | + }); | |
| 260 | + }); | |
| 261 | + }, | |
| 262 | + /** 删除按钮操作 */ | |
| 263 | + handleDelete(row) { | |
| 264 | + const id = row.id; | |
| 265 | + this.$confirm('是否确认删除支付商户信息编号为"' + id + '"的数据项?', "警告", { | |
| 266 | + confirmButtonText: "确定", | |
| 267 | + cancelButtonText: "取消", | |
| 268 | + type: "warning" | |
| 269 | + }).then(function() { | |
| 270 | + return deleteMerchant(id); | |
| 271 | + }).then(() => { | |
| 272 | + this.getList(); | |
| 273 | + this.msgSuccess("删除成功"); | |
| 274 | + }) | |
| 275 | + }, | |
| 276 | + /** 导出按钮操作 */ | |
| 277 | + handleExport() { | |
| 278 | + // 处理查询参数 | |
| 279 | + let params = {...this.queryParams}; | |
| 280 | + params.pageNo = undefined; | |
| 281 | + params.pageSize = undefined; | |
| 282 | + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 283 | + // 执行导出 | |
| 284 | + this.$confirm('是否确认导出所有支付商户信息数据项?', "警告", { | |
| 285 | + confirmButtonText: "确定", | |
| 286 | + cancelButtonText: "取消", | |
| 287 | + type: "warning" | |
| 288 | + }).then(function() { | |
| 289 | + return exportMerchantExcel(params); | |
| 290 | + }).then(response => { | |
| 291 | + this.downloadExcel(response, '支付商户信息.xls'); | |
| 292 | + }) | |
| 293 | + } | |
| 294 | + } | |
| 295 | +}; | |
| 296 | +</script> | ... | ... |
yudao-admin-ui/src/views/pay/order/index.vue
0 → 100755
| 1 | +<template> | |
| 2 | + <div class="app-container"> | |
| 3 | + | |
| 4 | + <!-- 搜索工作栏 --> | |
| 5 | + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="120px"> | |
| 6 | + <el-form-item label="所属商户" prop="merchantId"> | |
| 7 | + <el-select | |
| 8 | + v-model="queryParams.merchantId" | |
| 9 | + clearable | |
| 10 | + @clear="()=>{queryParams.merchantId = null}" | |
| 11 | + filterable | |
| 12 | + remote | |
| 13 | + reserve-keyword | |
| 14 | + placeholder="请选择所属商户" | |
| 15 | + @change="handleGetAppListByMerchantId" | |
| 16 | + :remote-method="handleGetMerchantListByName" | |
| 17 | + :loading="merchantLoading"> | |
| 18 | + <el-option | |
| 19 | + v-for="item in merchantList" | |
| 20 | + :key="item.id" | |
| 21 | + :label="item.name" | |
| 22 | + :value="item.id"> | |
| 23 | + </el-option> | |
| 24 | + </el-select> | |
| 25 | + </el-form-item> | |
| 26 | + <el-form-item label="应用编号" prop="appId"> | |
| 27 | + <el-select | |
| 28 | + clearable | |
| 29 | + v-model="queryParams.appId" | |
| 30 | + filterable | |
| 31 | + placeholder="请选择应用信息"> | |
| 32 | + <el-option | |
| 33 | + v-for="item in appList" | |
| 34 | + :key="item.id" | |
| 35 | + :label="item.name" | |
| 36 | + :value="item.id"> | |
| 37 | + </el-option> | |
| 38 | + </el-select> | |
| 39 | + </el-form-item> | |
| 40 | + <el-form-item label="渠道编码" prop="channelCode"> | |
| 41 | + <el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable | |
| 42 | + size="small" @clear="()=>{queryParams.channelCode = null}"> | |
| 43 | + <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/> | |
| 44 | + </el-select> | |
| 45 | + </el-form-item> | |
| 46 | + <el-form-item label="商户订单编号" prop="merchantOrderId"> | |
| 47 | + <el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户订单编号" clearable size="small" | |
| 48 | + @keyup.enter.native="handleQuery"/> | |
| 49 | + </el-form-item> | |
| 50 | + <el-form-item label="渠道订单号" prop="channelOrderNo"> | |
| 51 | + <el-input v-model="queryParams.channelOrderNo" placeholder="请输入渠道订单号" clearable size="small" | |
| 52 | + @keyup.enter.native="handleQuery"/> | |
| 53 | + </el-form-item> | |
| 54 | + <el-form-item label="支付状态" prop="status"> | |
| 55 | + <el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small"> | |
| 56 | + <el-option v-for="dict in payOrderDictDatum" :key="parseInt(dict.value)" | |
| 57 | + :label="dict.label" :value="parseInt(dict.value)"/> | |
| 58 | + </el-select> | |
| 59 | + </el-form-item> | |
| 60 | + <el-form-item label="退款状态" prop="refundStatus"> | |
| 61 | + <el-select v-model="queryParams.refundStatus" placeholder="请选择退款状态" clearable size="small"> | |
| 62 | + <el-option v-for="dict in payOrderRefundDictDatum" :key="parseInt(dict.value)" | |
| 63 | + :label="dict.label" :value="parseInt(dict.value)"/> | |
| 64 | + </el-select> | |
| 65 | + </el-form-item> | |
| 66 | + <el-form-item label="回调商户状态" prop="notifyStatus"> | |
| 67 | + <el-select v-model="queryParams.notifyStatus" placeholder="请选择订单回调商户状态" clearable size="small"> | |
| 68 | + <el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)" | |
| 69 | + :label="dict.label" :value="parseInt(dict.value)"/> | |
| 70 | + </el-select> | |
| 71 | + </el-form-item> | |
| 72 | + <el-form-item label="创建时间"> | |
| 73 | + <el-date-picker | |
| 74 | + v-model="dateRangeCreateTime" size="small" style="width: 350px" | |
| 75 | + value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" | |
| 76 | + :default-time="['00:00:00','23:59:59']" start-placeholder="开始日期" end-placeholder="结束日期"> | |
| 77 | + </el-date-picker> | |
| 78 | + </el-form-item> | |
| 79 | + <el-form-item> | |
| 80 | + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> | |
| 81 | + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> | |
| 82 | + </el-form-item> | |
| 83 | + </el-form> | |
| 84 | + | |
| 85 | + <!-- 操作工具栏 --> | |
| 86 | + <el-row :gutter="10" class="mb8"> | |
| 87 | + <el-col :span="1.5"> | |
| 88 | + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" | |
| 89 | + v-hasPermi="['pay:order:export']">导出 | |
| 90 | + </el-button> | |
| 91 | + </el-col> | |
| 92 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | |
| 93 | + </el-row> | |
| 94 | + | |
| 95 | + <!-- 列表 --> | |
| 96 | + <el-table v-loading="loading" :data="list"> | |
| 97 | + <el-table-column label="订单编号" align="center" prop="id" width="80"/> | |
| 98 | +<!-- <el-table-column label="商户名称" align="center" prop="merchantName" width="120"/>--> | |
| 99 | +<!-- <el-table-column label="应用名称" align="center" prop="appName" width="120"/>--> | |
| 100 | + <el-table-column label="支付渠道" align="center" width="130"> | |
| 101 | + <template v-slot="scope"> | |
| 102 | + <el-popover trigger="hover" placement="top"> | |
| 103 | + <p>商户名称: {{ scope.row.merchantName }}</p> | |
| 104 | + <p>应用名称: {{ scope.row.appName }}</p> | |
| 105 | + <p>渠道名称: {{ scope.row.channelCodeName }}</p> | |
| 106 | + <div slot="reference" class="name-wrapper"> | |
| 107 | + {{ scope.row.channelCodeName }} | |
| 108 | + </div> | |
| 109 | + </el-popover> | |
| 110 | + </template> | |
| 111 | + </el-table-column> | |
| 112 | + <el-table-column label="支付订单" align="left" width="250"> | |
| 113 | + <template v-slot="scope"> | |
| 114 | + <p class="order-font"><el-tag size="mini">商户</el-tag> {{scope.row.merchantOrderId}}</p> | |
| 115 | + <p class="order-font"><el-tag size="mini" type="warning">支付</el-tag> {{scope.row.channelOrderNo}}</p> | |
| 116 | + </template> | |
| 117 | + </el-table-column> | |
| 118 | +<!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>--> | |
| 119 | +<!-- <el-table-column label="渠道订单号" align="center" prop="channelOrderNo" width="140"/>--> | |
| 120 | + <el-table-column label="商品标题" align="center" prop="subject" width="180" :show-overflow-tooltip="true"/> | |
| 121 | + <el-table-column label="支付金额" align="center" prop="amount" width="100"> | |
| 122 | + <template slot-scope="scope"> | |
| 123 | + ¥{{ parseFloat(scope.row.amount / 100).toFixed(2) }} | |
| 124 | + </template> | |
| 125 | + </el-table-column> | |
| 126 | + <el-table-column label="手续金额" align="center" prop="channelFeeAmount" width="100"> | |
| 127 | + <template slot-scope="scope"> | |
| 128 | + ¥{{ parseFloat(scope.row.channelFeeAmount / 100).toFixed(2) }} | |
| 129 | + </template> | |
| 130 | + </el-table-column> | |
| 131 | + <el-table-column label="退款金额" align="center" prop="refundAmount" width="100"> | |
| 132 | + <template slot-scope="scope"> | |
| 133 | + ¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }} | |
| 134 | + </template> | |
| 135 | + </el-table-column> | |
| 136 | + <el-table-column label="支付状态" align="center" prop="status"> | |
| 137 | + <template slot-scope="scope"> | |
| 138 | + <span>{{ getDictDataLabel(DICT_TYPE.PAY_ORDER_STATUS, scope.row.status) }}</span> | |
| 139 | + </template> | |
| 140 | + </el-table-column> | |
| 141 | +<!-- <el-table-column label="退款状态" align="center" prop="refundStatus">--> | |
| 142 | +<!-- <template slot-scope="scope">--> | |
| 143 | +<!-- <span>{{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, scope.row.refundStatus) }}</span>--> | |
| 144 | +<!-- </template>--> | |
| 145 | +<!-- </el-table-column>--> | |
| 146 | + <el-table-column label="回调状态" align="center" prop="notifyStatus" width="100"> | |
| 147 | + <template slot-scope="scope"> | |
| 148 | + <span>{{ getDictDataLabel(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS, scope.row.notifyStatus) }}</span> | |
| 149 | + </template> | |
| 150 | + </el-table-column> | |
| 151 | + <el-table-column label="创建时间" align="center" prop="createTime" width="100"> | |
| 152 | + <template slot-scope="scope"> | |
| 153 | + <span>{{ parseTime(scope.row.createTime) }}</span> | |
| 154 | + </template> | |
| 155 | + </el-table-column> | |
| 156 | + <el-table-column label="支付时间" align="center" prop="successTime" width="100"> | |
| 157 | + <template slot-scope="scope"> | |
| 158 | + <span>{{ parseTime(scope.row.successTime) }}</span> | |
| 159 | + </template> | |
| 160 | + </el-table-column> | |
| 161 | + <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> | |
| 162 | + <template slot-scope="scope"> | |
| 163 | + <el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)" | |
| 164 | + v-hasPermi="['pay:order:query']">查看详情 | |
| 165 | + </el-button> | |
| 166 | + </template> | |
| 167 | + </el-table-column> | |
| 168 | + </el-table> | |
| 169 | + <!-- 分页组件 --> | |
| 170 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | |
| 171 | + @pagination="getList"/> | |
| 172 | + | |
| 173 | + <!-- 对话框(添加 / 修改) --> | |
| 174 | + <el-dialog title="订单详情" :visible.sync="open" width="50%"> | |
| 175 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 176 | + <el-descriptions-item label="商户名称">{{ orderDetail.merchantName }}</el-descriptions-item> | |
| 177 | + <el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item> | |
| 178 | + <el-descriptions-item label="商品名称">{{ orderDetail.subject }}</el-descriptions-item> | |
| 179 | + </el-descriptions> | |
| 180 | + <el-divider></el-divider> | |
| 181 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 182 | + <el-descriptions-item label="商户订单号"> | |
| 183 | + <el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag> | |
| 184 | + </el-descriptions-item> | |
| 185 | + <el-descriptions-item label="渠道订单号"> | |
| 186 | + <el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag> | |
| 187 | + </el-descriptions-item> | |
| 188 | + <el-descriptions-item label="支付订单号"> | |
| 189 | + <el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small"> | |
| 190 | + {{ orderDetail.payOrderExtension.no }} | |
| 191 | + </el-tag> | |
| 192 | + </el-descriptions-item> | |
| 193 | + <el-descriptions-item label="金额"> | |
| 194 | + <el-tag type="success" size="small">{{ parseFloat(orderDetail.amount / 100, 2) }}</el-tag> | |
| 195 | + </el-descriptions-item> | |
| 196 | + <el-descriptions-item label="手续费"> | |
| 197 | + <el-tag type="warning" size="small">{{ parseFloat(orderDetail.channelFeeAmount / 100, 2) }}</el-tag> | |
| 198 | + </el-descriptions-item> | |
| 199 | + <el-descriptions-item label="手续费比例"> | |
| 200 | + {{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}% | |
| 201 | + </el-descriptions-item> | |
| 202 | + <el-descriptions-item label="支付状态"> | |
| 203 | + <el-tag :type="statusType" size="small"> | |
| 204 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_STATUS, orderDetail.status) }} | |
| 205 | + </el-tag> | |
| 206 | + </el-descriptions-item> | |
| 207 | + <el-descriptions-item label="回调状态"> | |
| 208 | + <el-tag :type="notifyStatusType" size="small"> | |
| 209 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS, orderDetail.notifyStatus) }} | |
| 210 | + </el-tag> | |
| 211 | + </el-descriptions-item> | |
| 212 | + <el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item> | |
| 213 | + <el-descriptions-item label="创建时间">{{ parseTime(orderDetail.createTime) }}</el-descriptions-item> | |
| 214 | + <el-descriptions-item label="支付时间">{{ parseTime(orderDetail.successTime) }}</el-descriptions-item> | |
| 215 | + <el-descriptions-item label="失效时间">{{ parseTime(orderDetail.expireTime) }}</el-descriptions-item> | |
| 216 | + <el-descriptions-item label="通知时间">{{ parseTime(orderDetail.notifyTime) }}</el-descriptions-item> | |
| 217 | + </el-descriptions> | |
| 218 | + <el-divider></el-divider> | |
| 219 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 220 | + <el-descriptions-item label="支付渠道">{{ orderDetail.channelCodeName }}</el-descriptions-item> | |
| 221 | + <el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item> | |
| 222 | + <el-descriptions-item label="退款状态"> | |
| 223 | + <el-tag :type="refundStatusType" size="small"> | |
| 224 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, orderDetail.refundStatus) }} | |
| 225 | + </el-tag> | |
| 226 | + </el-descriptions-item> | |
| 227 | + <el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item> | |
| 228 | + <el-descriptions-item label="退款金额"> | |
| 229 | + <el-tag type="warning"> | |
| 230 | + {{ parseFloat(orderDetail.refundAmount / 100, 2) }} | |
| 231 | + </el-tag> | |
| 232 | + </el-descriptions-item> | |
| 233 | + </el-descriptions> | |
| 234 | + <el-divider></el-divider> | |
| 235 | + <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> | |
| 236 | + <el-descriptions-item label="商品描述"> | |
| 237 | + {{ orderDetail.body }} | |
| 238 | + </el-descriptions-item> | |
| 239 | + <el-descriptions-item label="支付通道异步回调内容"> | |
| 240 | + {{ orderDetail.payOrderExtension.channelNotifyData }} | |
| 241 | + </el-descriptions-item> | |
| 242 | + </el-descriptions> | |
| 243 | + </el-dialog> | |
| 244 | + </div> | |
| 245 | +</template> | |
| 246 | + | |
| 247 | +<script> | |
| 248 | +import {getOrder, getOrderPage, exportOrderExcel} from "@/api/pay/order"; | |
| 249 | +import {getMerchantListByName} from "@/api/pay/merchant"; | |
| 250 | +import {getAppListByMerchantId} from "@/api/pay/app"; | |
| 251 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | |
| 252 | +import {payOrderNotifyStatusEnum, payOrderRefundStatusEnum, payOrderStatusEnum} from "@/utils/constants"; | |
| 253 | +import { getNowDateTime} from "@/utils/ruoyi"; | |
| 254 | + | |
| 255 | +const defaultOrderDetail = { | |
| 256 | + merchantName: '', | |
| 257 | + appName: '', | |
| 258 | + channelCodeName: '', | |
| 259 | + subject: '', | |
| 260 | + merchantOrderId: null, | |
| 261 | + channelOrderNo: '', | |
| 262 | + body: '', | |
| 263 | + amount: null, | |
| 264 | + channelFeeRate: null, | |
| 265 | + channelFeeAmount: null, | |
| 266 | + userIp: '', | |
| 267 | + status: null, | |
| 268 | + notifyUrl: '', | |
| 269 | + notifyStatus: null, | |
| 270 | + refundStatus: null, | |
| 271 | + refundTimes: '', | |
| 272 | + refundAmount: null, | |
| 273 | + createTime: '', | |
| 274 | + successTime: '', | |
| 275 | + notifyTime: '', | |
| 276 | + expireTime: '', | |
| 277 | + payOrderExtension: { | |
| 278 | + channelNotifyData: '', | |
| 279 | + no: '' | |
| 280 | + } | |
| 281 | +}; | |
| 282 | + | |
| 283 | +export default { | |
| 284 | + name: "Order", | |
| 285 | + components: {}, | |
| 286 | + data() { | |
| 287 | + return { | |
| 288 | + // 遮罩层 | |
| 289 | + loading: true, | |
| 290 | + // 显示搜索条件 | |
| 291 | + showSearch: true, | |
| 292 | + // 总条数 | |
| 293 | + total: 0, | |
| 294 | + // 支付订单列表 | |
| 295 | + list: [], | |
| 296 | + // 弹出层标题 | |
| 297 | + title: "", | |
| 298 | + // 是否显示弹出层 | |
| 299 | + open: false, | |
| 300 | + dateRangeExpireTime: [], | |
| 301 | + dateRangeSuccessTime: [], | |
| 302 | + dateRangeNotifyTime: [], | |
| 303 | + dateRangeCreateTime: [], | |
| 304 | + // 查询参数 | |
| 305 | + queryParams: { | |
| 306 | + pageNo: 1, | |
| 307 | + pageSize: 10, | |
| 308 | + merchantId: null, | |
| 309 | + appId: null, | |
| 310 | + channelId: null, | |
| 311 | + channelCode: null, | |
| 312 | + merchantOrderId: null, | |
| 313 | + subject: null, | |
| 314 | + body: null, | |
| 315 | + notifyUrl: null, | |
| 316 | + notifyStatus: null, | |
| 317 | + amount: null, | |
| 318 | + channelFeeRate: null, | |
| 319 | + channelFeeAmount: null, | |
| 320 | + status: null, | |
| 321 | + userIp: null, | |
| 322 | + successExtensionId: null, | |
| 323 | + refundStatus: null, | |
| 324 | + refundTimes: null, | |
| 325 | + refundAmount: null, | |
| 326 | + channelUserId: null, | |
| 327 | + channelOrderNo: null, | |
| 328 | + }, | |
| 329 | + // 商户加载遮罩层 | |
| 330 | + merchantLoading: false, | |
| 331 | + // 商户列表集合 | |
| 332 | + merchantList: null, | |
| 333 | + // 支付应用列表集合 | |
| 334 | + appList: null, | |
| 335 | + // 支付渠道编码字典数据集合 | |
| 336 | + payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE), | |
| 337 | + // 订单回调商户状态字典数据集合 | |
| 338 | + payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS), | |
| 339 | + // 订单状态字典数据集合 | |
| 340 | + payOrderDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_STATUS), | |
| 341 | + // 订单退款状态字典数据集合 | |
| 342 | + payOrderRefundDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_REFUND_STATUS), | |
| 343 | + orderDetail: JSON.parse(JSON.stringify(defaultOrderDetail)), | |
| 344 | + // el-tag订单状态type值 | |
| 345 | + statusType: '', | |
| 346 | + // el-tag订单回调通知状态type值 | |
| 347 | + notifyStatusType: '', | |
| 348 | + // el-tag订单退款状态type值 | |
| 349 | + refundStatusType: '', | |
| 350 | + }; | |
| 351 | + }, | |
| 352 | + created() { | |
| 353 | + // 初始化默认时间 | |
| 354 | + this.initTime(); | |
| 355 | + this.getList(); | |
| 356 | + this.handleGetMerchantListByName(null); | |
| 357 | + }, | |
| 358 | + methods: { | |
| 359 | + initTime(){ | |
| 360 | + this.dateRangeCreateTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")]; | |
| 361 | + }, | |
| 362 | + /** 查询列表 */ | |
| 363 | + getList() { | |
| 364 | + // 判断选择的日期是否超过了一个月 | |
| 365 | + let oneMonthTime = 31 * 24 * 3600 * 1000; | |
| 366 | + if (this.dateRangeCreateTime == null){ | |
| 367 | + this.initTime(); | |
| 368 | + } else { | |
| 369 | + let minDateTime = new Date(this.dateRangeCreateTime[0]).getTime(); | |
| 370 | + let maxDateTime = new Date(this.dateRangeCreateTime[1]).getTime() | |
| 371 | + if (maxDateTime - minDateTime > oneMonthTime) { | |
| 372 | + this.$message.error('时间范围最大为 31 天!'); | |
| 373 | + return false; | |
| 374 | + } | |
| 375 | + } | |
| 376 | + | |
| 377 | + this.loading = true; | |
| 378 | + // 处理查询参数 | |
| 379 | + let params = {...this.queryParams}; | |
| 380 | + this.addBeginAndEndTime(params, this.dateRangeExpireTime, 'expireTime'); | |
| 381 | + this.addBeginAndEndTime(params, this.dateRangeSuccessTime, 'successTime'); | |
| 382 | + this.addBeginAndEndTime(params, this.dateRangeNotifyTime, 'notifyTime'); | |
| 383 | + this.addDateRange(params, this.dateRangeCreateTime, 'CreateTime'); | |
| 384 | + // 执行查询 | |
| 385 | + getOrderPage(params).then(response => { | |
| 386 | + this.list = response.data.list; | |
| 387 | + this.total = response.data.total; | |
| 388 | + this.loading = false; | |
| 389 | + }); | |
| 390 | + }, | |
| 391 | + /** 取消按钮 */ | |
| 392 | + cancel() { | |
| 393 | + this.open = false; | |
| 394 | + }, | |
| 395 | + /** 搜索按钮操作 */ | |
| 396 | + handleQuery() { | |
| 397 | + this.queryParams.pageNo = 1; | |
| 398 | + this.getList(); | |
| 399 | + }, | |
| 400 | + /** 重置按钮操作 */ | |
| 401 | + resetQuery() { | |
| 402 | + this.dateRangeSuccessTime = []; | |
| 403 | + this.dateRangeNotifyTime = []; | |
| 404 | + this.dateRangeExpireTime = []; | |
| 405 | + this.resetForm("queryForm"); | |
| 406 | + this.initTime(); | |
| 407 | + this.handleQuery(); | |
| 408 | + }, | |
| 409 | + /** | |
| 410 | + * 查看订单详情 | |
| 411 | + */ | |
| 412 | + handleQueryDetails(row) { | |
| 413 | + this.orderDetail = JSON.parse(JSON.stringify(defaultOrderDetail)); | |
| 414 | + getOrder(row.id).then(response => { | |
| 415 | + this.orderDetail = response.data; | |
| 416 | + if (response.data.payOrderExtension === null) { | |
| 417 | + this.orderDetail.payOrderExtension = Object.assign(defaultOrderDetail.payOrderExtension, {}); | |
| 418 | + } | |
| 419 | + switch (this.orderDetail.status) { | |
| 420 | + case payOrderStatusEnum.WAITING.status: | |
| 421 | + this.statusType = "info"; | |
| 422 | + break; | |
| 423 | + case payOrderStatusEnum.SUCCESS.status: | |
| 424 | + this.statusType = "success"; | |
| 425 | + break; | |
| 426 | + case payOrderStatusEnum.CLOSED.status: | |
| 427 | + this.statusType = "danger"; | |
| 428 | + break; | |
| 429 | + } | |
| 430 | + switch (this.orderDetail.notifyStatus) { | |
| 431 | + case payOrderNotifyStatusEnum.NO.status: | |
| 432 | + this.notifyStatusType = "info"; | |
| 433 | + break; | |
| 434 | + case payOrderNotifyStatusEnum.SUCCESS.status: | |
| 435 | + this.notifyStatusType = "success"; | |
| 436 | + break; | |
| 437 | + case payOrderNotifyStatusEnum.FAILURE.status: | |
| 438 | + this.notifyStatusType = "danger"; | |
| 439 | + break; | |
| 440 | + } | |
| 441 | + | |
| 442 | + switch (this.orderDetail.refundStatus) { | |
| 443 | + case payOrderRefundStatusEnum.NO.status: | |
| 444 | + this.refundStatusType = "success"; | |
| 445 | + break; | |
| 446 | + case payOrderRefundStatusEnum.SOME.status: | |
| 447 | + this.refundStatusType = "warning"; | |
| 448 | + break; | |
| 449 | + case payOrderRefundStatusEnum.ALL.status: | |
| 450 | + this.refundStatusType = "danger"; | |
| 451 | + break; | |
| 452 | + } | |
| 453 | + this.open = true; | |
| 454 | + }); | |
| 455 | + | |
| 456 | + }, | |
| 457 | + /** 导出按钮操作 */ | |
| 458 | + handleExport() { | |
| 459 | + // 处理查询参数 | |
| 460 | + let params = {...this.queryParams}; | |
| 461 | + params.pageNo = undefined; | |
| 462 | + params.pageSize = undefined; | |
| 463 | + this.addBeginAndEndTime(params, this.dateRangeExpireTime, 'expireTime'); | |
| 464 | + this.addBeginAndEndTime(params, this.dateRangeSuccessTime, 'successTime'); | |
| 465 | + this.addBeginAndEndTime(params, this.dateRangeNotifyTime, 'notifyTime'); | |
| 466 | + this.addDateRange(params, this.dateRangeCreateTime, 'CreateTime'); | |
| 467 | + // 执行导出 | |
| 468 | + this.$confirm('是否确认导出所有支付订单数据项?', "警告", { | |
| 469 | + confirmButtonText: "确定", | |
| 470 | + cancelButtonText: "取消", | |
| 471 | + type: "warning" | |
| 472 | + }).then(function () { | |
| 473 | + return exportOrderExcel(params); | |
| 474 | + }).then(response => { | |
| 475 | + this.downloadExcel(response, '支付订单.xls'); | |
| 476 | + }) | |
| 477 | + }, | |
| 478 | + /** | |
| 479 | + * 根据商户名称模糊匹配商户信息 | |
| 480 | + * @param name 商户名称 | |
| 481 | + */ | |
| 482 | + handleGetMerchantListByName(name) { | |
| 483 | + getMerchantListByName(name).then(response => { | |
| 484 | + this.merchantList = response.data; | |
| 485 | + this.merchantLoading = false; | |
| 486 | + }); | |
| 487 | + }, | |
| 488 | + /** | |
| 489 | + * 根据商户 ID 查询支付应用信息 | |
| 490 | + */ | |
| 491 | + handleGetAppListByMerchantId() { | |
| 492 | + this.queryParams.appId = null; | |
| 493 | + getAppListByMerchantId(this.queryParams.merchantId).then(response => { | |
| 494 | + this.appList = response.data; | |
| 495 | + }); | |
| 496 | + } | |
| 497 | + } | |
| 498 | +}; | |
| 499 | +</script> | |
| 500 | +<style> | |
| 501 | +.desc-label { | |
| 502 | + font-weight: bold; | |
| 503 | + | |
| 504 | +} | |
| 505 | + | |
| 506 | +.tag-purple { | |
| 507 | + color: #722ed1; | |
| 508 | + background: #f9f0ff; | |
| 509 | + border-color: #d3adf7; | |
| 510 | +} | |
| 511 | + | |
| 512 | +.tag-cyan { | |
| 513 | + color: #13c2c2; | |
| 514 | + background: #e6fffb; | |
| 515 | + border-color: #87e8de; | |
| 516 | +} | |
| 517 | + | |
| 518 | +.tag-pink { | |
| 519 | + color: #eb2f96; | |
| 520 | + background: #fff0f6; | |
| 521 | + border-color: #ffadd2; | |
| 522 | +} | |
| 523 | + | |
| 524 | +.order-font{ | |
| 525 | + font-size: 12px; | |
| 526 | + padding: 2px 0; | |
| 527 | +} | |
| 528 | +</style> | ... | ... |
yudao-admin-ui/src/views/pay/refund/index.vue
0 → 100755
| 1 | +<template> | |
| 2 | + <div class="app-container"> | |
| 3 | + | |
| 4 | + <!-- 搜索工作栏 --> | |
| 5 | + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="120px"> | |
| 6 | + <el-form-item label="所属商户" prop="merchantId"> | |
| 7 | + <el-select | |
| 8 | + v-model="queryParams.merchantId" | |
| 9 | + clearable | |
| 10 | + @clear="()=>{queryParams.merchantId = null}" | |
| 11 | + filterable | |
| 12 | + remote | |
| 13 | + reserve-keyword | |
| 14 | + placeholder="请选择所属商户" | |
| 15 | + @change="handleGetAppListByMerchantId" | |
| 16 | + :remote-method="handleGetMerchantListByName" | |
| 17 | + :loading="merchantLoading"> | |
| 18 | + <el-option | |
| 19 | + v-for="item in merchantList" | |
| 20 | + :key="item.id" | |
| 21 | + :label="item.name" | |
| 22 | + :value="item.id"> | |
| 23 | + </el-option> | |
| 24 | + </el-select> | |
| 25 | + </el-form-item> | |
| 26 | + <el-form-item label="应用编号" prop="appId"> | |
| 27 | + <el-select | |
| 28 | + clearable | |
| 29 | + v-model="queryParams.appId" | |
| 30 | + filterable | |
| 31 | + placeholder="请选择应用信息"> | |
| 32 | + <el-option | |
| 33 | + v-for="item in appList" | |
| 34 | + :key="item.id" | |
| 35 | + :label="item.name" | |
| 36 | + :value="item.id"> | |
| 37 | + </el-option> | |
| 38 | + </el-select> | |
| 39 | + </el-form-item> | |
| 40 | + <el-form-item label="渠道编码" prop="channelCode"> | |
| 41 | + <el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable | |
| 42 | + size="small" @clear="()=>{queryParams.channelCode = null}"> | |
| 43 | + <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/> | |
| 44 | + </el-select> | |
| 45 | + </el-form-item> | |
| 46 | + <el-form-item label="退款类型" prop="type"> | |
| 47 | + <el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable size="small"> | |
| 48 | + <el-option v-for="dict in payRefundOrderTypeDictDatum" :key="parseInt(dict.value)" | |
| 49 | + :label="dict.label" :value="parseInt(dict.value)"/> | |
| 50 | + </el-select> | |
| 51 | + </el-form-item> | |
| 52 | + <el-form-item label="商户退款订单号" prop="merchantRefundNo"> | |
| 53 | + <el-input v-model="queryParams.merchantRefundNo" placeholder="请输入商户退款订单号" clearable size="small" | |
| 54 | + @keyup.enter.native="handleQuery"/> | |
| 55 | + </el-form-item> | |
| 56 | + | |
| 57 | + <el-form-item label="退款状态" prop="status"> | |
| 58 | + <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable size="small"> | |
| 59 | + <el-option v-for="dict in payRefundOrderDictDatum" :key="parseInt(dict.value)" | |
| 60 | + :label="dict.label" :value="parseInt(dict.value)"/> | |
| 61 | + </el-select> | |
| 62 | + </el-form-item> | |
| 63 | + | |
| 64 | + <el-form-item label="退款回调状态" prop="notifyStatus"> | |
| 65 | + <el-select v-model="queryParams.notifyStatus" placeholder="请选择通知商户退款结果的回调状态" clearable size="small"> | |
| 66 | + <el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)" | |
| 67 | + :label="dict.label" :value="parseInt(dict.value)"/> | |
| 68 | + </el-select> | |
| 69 | + </el-form-item> | |
| 70 | + <el-form-item label="创建时间"> | |
| 71 | + <el-date-picker | |
| 72 | + v-model="dateRangeCreateTime" size="small" style="width: 350px" | |
| 73 | + value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" | |
| 74 | + :default-time="['00:00:00','23:59:59']" start-placeholder="开始日期" end-placeholder="结束日期"> | |
| 75 | + </el-date-picker> | |
| 76 | + </el-form-item> | |
| 77 | + <el-form-item> | |
| 78 | + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> | |
| 79 | + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> | |
| 80 | + </el-form-item> | |
| 81 | + </el-form> | |
| 82 | + | |
| 83 | + <!-- 操作工具栏 --> | |
| 84 | + <el-row :gutter="10" class="mb8"> | |
| 85 | + <el-col :span="1.5"> | |
| 86 | + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" | |
| 87 | + v-hasPermi="['pay:refund:export']">导出 | |
| 88 | + </el-button> | |
| 89 | + </el-col> | |
| 90 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | |
| 91 | + </el-row> | |
| 92 | + | |
| 93 | + <!-- 列表 --> | |
| 94 | + <el-table v-loading="loading" :data="list"> | |
| 95 | + <el-table-column label="编号" align="center" prop="id"/> | |
| 96 | + <!-- <el-table-column label="商户名称" align="center" prop="merchantName" width="120"/>--> | |
| 97 | + <!-- <el-table-column label="应用名称" align="center" prop="appName" width="120"/>--> | |
| 98 | + <el-table-column label="支付渠道" align="center" width="130"> | |
| 99 | + <template v-slot="scope"> | |
| 100 | + <el-popover trigger="hover" placement="top"> | |
| 101 | + <p>商户名称: {{ scope.row.merchantName }}</p> | |
| 102 | + <p>应用名称: {{ scope.row.appName }}</p> | |
| 103 | + <p>渠道名称: {{ scope.row.channelCodeName }}</p> | |
| 104 | + <div slot="reference" class="name-wrapper"> | |
| 105 | + {{ scope.row.channelCodeName }} | |
| 106 | + </div> | |
| 107 | + </el-popover> | |
| 108 | + </template> | |
| 109 | + </el-table-column> | |
| 110 | + <!-- <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140"/>--> | |
| 111 | + <!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>--> | |
| 112 | + <el-table-column label="商户订单号" align="left" width="230"> | |
| 113 | + <template v-slot="scope"> | |
| 114 | + <p class="order-font"> | |
| 115 | + <el-tag size="mini">退款</el-tag> | |
| 116 | + {{ scope.row.merchantRefundNo }} | |
| 117 | + </p> | |
| 118 | + <p class="order-font"> | |
| 119 | + <el-tag type="success">交易</el-tag> | |
| 120 | + {{ scope.row.merchantOrderId }} | |
| 121 | + </p> | |
| 122 | + </template> | |
| 123 | + </el-table-column> | |
| 124 | + <el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250"> | |
| 125 | + <template v-slot="scope"> | |
| 126 | + <p class="order-font"> | |
| 127 | + <el-tag size="mini">交易</el-tag> | |
| 128 | + {{ scope.row.tradeNo }} | |
| 129 | + </p> | |
| 130 | + <p class="order-font"> | |
| 131 | + <el-tag size="mini" type="warning">渠道</el-tag> | |
| 132 | + {{ scope.row.channelOrderNo }} | |
| 133 | + </p> | |
| 134 | + </template> | |
| 135 | + </el-table-column> | |
| 136 | + <el-table-column label="支付金额(元)" align="center" prop="payAmount" width="100"> | |
| 137 | + <template v-slot="scope" class=""> | |
| 138 | + ¥{{ parseFloat(scope.row.payAmount / 100).toFixed(2) }} | |
| 139 | + </template> | |
| 140 | + </el-table-column> | |
| 141 | + <el-table-column label="退款金额(元)" align="center" prop="refundAmount" width="100"> | |
| 142 | + <template scope="scope"> | |
| 143 | + ¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }} | |
| 144 | + </template> | |
| 145 | + </el-table-column> | |
| 146 | + <el-table-column label="退款类型" align="center" prop="type" width="80"> | |
| 147 | + <template v-slot="scope"> | |
| 148 | + <el-tag :type="findByRefundTypeGetStyle(scope.row.type)"> | |
| 149 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, scope.row.type) }} | |
| 150 | + </el-tag> | |
| 151 | + </template> | |
| 152 | + </el-table-column> | |
| 153 | + <el-table-column label="退款状态" align="center" prop="status"> | |
| 154 | + <template v-slot="scope"> | |
| 155 | + <el-tag :type="findByRefundStatusGetStyle(scope.row.status)"> | |
| 156 | + {{ getDictDataLabel(DICT_TYPE.PAY_REFUND_ORDER_STATUS, scope.row.status) }} | |
| 157 | + </el-tag> | |
| 158 | + </template> | |
| 159 | + </el-table-column> | |
| 160 | + <el-table-column label="回调状态" align="center" prop="notifyStatus"> | |
| 161 | + <template v-slot="scope"> | |
| 162 | + <el-tag :type="findByRefundStatusGetStyle(scope.row.notifyStatus)"> | |
| 163 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS, scope.row.notifyStatus) }} | |
| 164 | + </el-tag> | |
| 165 | + </template> | |
| 166 | + </el-table-column> | |
| 167 | + <el-table-column label="退款原因" align="center" prop="reason" width="140" :show-overflow-tooltip="true"/> | |
| 168 | + <el-table-column label="创建时间" align="center" prop="createTime" width="100"> | |
| 169 | + <template slot-scope="scope"> | |
| 170 | + <span>{{ parseTime(scope.row.createTime) }}</span> | |
| 171 | + </template> | |
| 172 | + </el-table-column> | |
| 173 | + <el-table-column label="退款成功时间" align="center" prop="successTime" width="100"> | |
| 174 | + <template slot-scope="scope"> | |
| 175 | + <span>{{ parseTime(scope.row.successTime) }}</span> | |
| 176 | + </template> | |
| 177 | + </el-table-column> | |
| 178 | + <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> | |
| 179 | + <template slot-scope="scope"> | |
| 180 | + <el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)" | |
| 181 | + v-hasPermi="['pay:order:query']">查看详情 | |
| 182 | + </el-button> | |
| 183 | + </template> | |
| 184 | + </el-table-column> | |
| 185 | + </el-table> | |
| 186 | + <!-- 分页组件 --> | |
| 187 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | |
| 188 | + @pagination="getList"/> | |
| 189 | + | |
| 190 | + <!-- 对话框(添加 / 修改) --> | |
| 191 | + <el-dialog title="退款订单详情" :visible.sync="open" width="700px" append-to-body> | |
| 192 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 193 | + <el-descriptions-item label="商户名称">{{ refundDetail.merchantName }}</el-descriptions-item> | |
| 194 | + <el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item> | |
| 195 | + <el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item> | |
| 196 | + </el-descriptions> | |
| 197 | + <el-divider></el-divider> | |
| 198 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 199 | + <el-descriptions-item label="商户退款单号"> | |
| 200 | + <el-tag size="mini">{{ refundDetail.merchantRefundNo }}</el-tag> | |
| 201 | + </el-descriptions-item> | |
| 202 | + <el-descriptions-item label="商户订单号">{{ refundDetail.merchantOrderId }}</el-descriptions-item> | |
| 203 | + <el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item> | |
| 204 | + </el-descriptions> | |
| 205 | + <el-divider></el-divider> | |
| 206 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 207 | + <el-descriptions-item label="支付金额"> | |
| 208 | + {{ parseFloat(refundDetail.payAmount / 100).toFixed(2) }} | |
| 209 | + </el-descriptions-item> | |
| 210 | + <el-descriptions-item label="退款金额" size="mini"> | |
| 211 | + <el-tag class="tag-purple" size="mini">{{ parseFloat(refundDetail.refundAmount / 100).toFixed(2) }}</el-tag> | |
| 212 | + </el-descriptions-item> | |
| 213 | + <el-descriptions-item label="退款类型"> | |
| 214 | + <el-tag size="mini" :type="findByRefundTypeGetStyle(refundDetail.type)"> | |
| 215 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, refundDetail.type) }} | |
| 216 | + </el-tag> | |
| 217 | + </el-descriptions-item> | |
| 218 | + <el-descriptions-item label="退款状态"> | |
| 219 | + <el-tag size="mini" :type="findByRefundStatusGetStyle(refundDetail.status)"> | |
| 220 | + {{ getDictDataLabel(DICT_TYPE.PAY_REFUND_ORDER_STATUS, refundDetail.status) }} | |
| 221 | + </el-tag> | |
| 222 | + </el-descriptions-item> | |
| 223 | + <el-descriptions-item label="创建时间">{{ parseTime(refundDetail.createTime) }}</el-descriptions-item> | |
| 224 | + <el-descriptions-item label="退款成功时间">{{ parseTime(refundDetail.successTime) }}</el-descriptions-item> | |
| 225 | + <el-descriptions-item label="退款失效时间">{{ parseTime(refundDetail.expireTime) }}</el-descriptions-item> | |
| 226 | + <el-descriptions-item label="更新时间">{{ parseTime(refundDetail.updateTime) }}</el-descriptions-item> | |
| 227 | + </el-descriptions> | |
| 228 | + <el-divider></el-divider> | |
| 229 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 230 | + <el-descriptions-item label="支付渠道"> | |
| 231 | + {{ refundDetail.channelCodeName }} | |
| 232 | + </el-descriptions-item> | |
| 233 | + <el-descriptions-item label="支付IP" size="mini"> | |
| 234 | + {{refundDetail.userIp}} | |
| 235 | + </el-descriptions-item> | |
| 236 | + <el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item> | |
| 237 | + <el-descriptions-item label="回调状态"> | |
| 238 | + <el-tag size="mini" :type="findByRefundStatusGetStyle(refundDetail.notifyStatus)"> | |
| 239 | + {{ getDictDataLabel(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS, refundDetail.notifyStatus) }} | |
| 240 | + </el-tag> | |
| 241 | + </el-descriptions-item> | |
| 242 | + <el-descriptions-item label="回调时间">{{ parseTime(refundDetail.notifyTime) }}</el-descriptions-item> | |
| 243 | + </el-descriptions> | |
| 244 | + <el-divider></el-divider> | |
| 245 | + <el-descriptions :column="2" label-class-name="desc-label"> | |
| 246 | + <el-descriptions-item label="渠道订单号">{{ refundDetail.channelOrderNo }}</el-descriptions-item> | |
| 247 | + <el-descriptions-item label="渠道退款单号">{{ refundDetail.channelRefundNo }}</el-descriptions-item> | |
| 248 | + <el-descriptions-item label="渠道错误码">{{refundDetail.channelErrorCode}}</el-descriptions-item> | |
| 249 | + <el-descriptions-item label="渠道错误码描述">{{refundDetail.channelErrorMsg}}</el-descriptions-item> | |
| 250 | + </el-descriptions> | |
| 251 | + <br> | |
| 252 | + <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border> | |
| 253 | + <el-descriptions-item label="渠道额外参数">{{ refundDetail.channelExtras }}</el-descriptions-item> | |
| 254 | + <el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item> | |
| 255 | + </el-descriptions> | |
| 256 | + </el-dialog> | |
| 257 | + </div> | |
| 258 | +</template> | |
| 259 | + | |
| 260 | +<script> | |
| 261 | +import {getRefundPage, exportRefundExcel, getRefund} from "@/api/pay/refund"; | |
| 262 | +import {getMerchantListByName} from "@/api/pay/merchant"; | |
| 263 | +import {getAppListByMerchantId} from "@/api/pay/app"; | |
| 264 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | |
| 265 | +import { | |
| 266 | + payOrderRefundStatusEnum, | |
| 267 | + payRefundStatusEnum | |
| 268 | +} from "@/utils/constants"; | |
| 269 | +import {getNowDateTime} from "@/utils/ruoyi"; | |
| 270 | + | |
| 271 | +const defaultRefundDetail = { | |
| 272 | + id: null, | |
| 273 | + appId: null, | |
| 274 | + appName: '', | |
| 275 | + channelCode: '', | |
| 276 | + channelCodeName: '', | |
| 277 | + channelErrorCode: '', | |
| 278 | + channelErrorMsg: '', | |
| 279 | + channelExtras: '', | |
| 280 | + channelId: null, | |
| 281 | + channelOrderNo: '', | |
| 282 | + channelRefundNo: '', | |
| 283 | + createTime: null, | |
| 284 | + expireTime: null, | |
| 285 | + merchantId: null, | |
| 286 | + merchantName: '', | |
| 287 | + merchantOrderId: '', | |
| 288 | + merchantRefundNo: '', | |
| 289 | + notifyStatus: null, | |
| 290 | + notifyTime: null, | |
| 291 | + notifyUrl: '', | |
| 292 | + orderId: null, | |
| 293 | + payAmount: null, | |
| 294 | + reason: '', | |
| 295 | + refundAmount: null, | |
| 296 | + status: null, | |
| 297 | + subject: '', | |
| 298 | + successTime: null, | |
| 299 | + tradeNo: '', | |
| 300 | + type: null, | |
| 301 | + userIp: '' | |
| 302 | +} | |
| 303 | + | |
| 304 | +export default { | |
| 305 | + name: "Refund", | |
| 306 | + components: {}, | |
| 307 | + data() { | |
| 308 | + return { | |
| 309 | + // 遮罩层 | |
| 310 | + loading: true, | |
| 311 | + // 显示搜索条件 | |
| 312 | + showSearch: true, | |
| 313 | + // 总条数 | |
| 314 | + total: 0, | |
| 315 | + // 退款订单列表 | |
| 316 | + list: [], | |
| 317 | + // 弹出层标题 | |
| 318 | + title: "", | |
| 319 | + // 是否显示弹出层 | |
| 320 | + open: false, | |
| 321 | + dateRangeExpireTime: [], | |
| 322 | + dateRangeSuccessTime: [], | |
| 323 | + dateRangeNotifyTime: [], | |
| 324 | + dateRangeCreateTime: [], | |
| 325 | + // 查询参数 | |
| 326 | + queryParams: { | |
| 327 | + pageNo: 1, | |
| 328 | + pageSize: 10, | |
| 329 | + merchantId: null, | |
| 330 | + appId: null, | |
| 331 | + channelId: null, | |
| 332 | + channelCode: null, | |
| 333 | + orderId: null, | |
| 334 | + tradeNo: null, | |
| 335 | + merchantOrderId: null, | |
| 336 | + merchantRefundNo: null, | |
| 337 | + notifyUrl: null, | |
| 338 | + notifyStatus: null, | |
| 339 | + status: null, | |
| 340 | + type: null, | |
| 341 | + payAmount: null, | |
| 342 | + refundAmount: null, | |
| 343 | + reason: null, | |
| 344 | + userIp: null, | |
| 345 | + channelOrderNo: null, | |
| 346 | + channelRefundNo: null, | |
| 347 | + channelErrorCode: null, | |
| 348 | + channelErrorMsg: null, | |
| 349 | + channelExtras: null, | |
| 350 | + }, | |
| 351 | + // 商户加载遮罩层 | |
| 352 | + merchantLoading: false, | |
| 353 | + // 商户列表集合 | |
| 354 | + merchantList: null, | |
| 355 | + // 支付应用列表集合 | |
| 356 | + appList: null, | |
| 357 | + // 支付渠道编码字典数据集合 | |
| 358 | + payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE), | |
| 359 | + // 订单退款状态字典数据集合 | |
| 360 | + payRefundOrderDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_STATUS), | |
| 361 | + // 退款订单类别字典数据集合 | |
| 362 | + payRefundOrderTypeDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_TYPE), | |
| 363 | + // 订单回调商户状态字典数据集合 | |
| 364 | + payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS), | |
| 365 | + // el-tag订单退款状态type值 | |
| 366 | + refundStatusType: '', | |
| 367 | + // 退款订单详情 | |
| 368 | + refundDetail: JSON.parse(JSON.stringify(defaultRefundDetail)), | |
| 369 | + }; | |
| 370 | + }, | |
| 371 | + created() { | |
| 372 | + this.initTime(); | |
| 373 | + this.getList(); | |
| 374 | + this.handleGetMerchantListByName(null); | |
| 375 | + }, | |
| 376 | + methods: { | |
| 377 | + initTime(){ | |
| 378 | + this.dateRangeCreateTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")]; | |
| 379 | + }, | |
| 380 | + /** 查询列表 */ | |
| 381 | + getList() { | |
| 382 | + // 判断选择的日期是否超过了一个月 | |
| 383 | + let oneMonthTime = 31 * 24 * 3600 * 1000; | |
| 384 | + if (this.dateRangeCreateTime == null){ | |
| 385 | + this.initTime(); | |
| 386 | + } else { | |
| 387 | + let minDateTime = new Date(this.dateRangeCreateTime[0]).getTime(); | |
| 388 | + let maxDateTime = new Date(this.dateRangeCreateTime[1]).getTime() | |
| 389 | + if (maxDateTime - minDateTime > oneMonthTime) { | |
| 390 | + this.$message.error('时间范围最大为 31 天!'); | |
| 391 | + return false; | |
| 392 | + } | |
| 393 | + } | |
| 394 | + this.loading = true; | |
| 395 | + // 处理查询参数 | |
| 396 | + let params = {...this.queryParams}; | |
| 397 | + this.addBeginAndEndTime(params, this.dateRangeExpireTime, 'expireTime'); | |
| 398 | + this.addBeginAndEndTime(params, this.dateRangeSuccessTime, 'successTime'); | |
| 399 | + this.addBeginAndEndTime(params, this.dateRangeNotifyTime, 'notifyTime'); | |
| 400 | + this.addDateRange(params, this.dateRangeCreateTime, 'CreateTime'); | |
| 401 | + // 执行查询 | |
| 402 | + getRefundPage(params).then(response => { | |
| 403 | + this.list = response.data.list; | |
| 404 | + this.total = response.data.total; | |
| 405 | + this.loading = false; | |
| 406 | + }); | |
| 407 | + }, | |
| 408 | + /** 取消按钮 */ | |
| 409 | + cancel() { | |
| 410 | + this.open = false; | |
| 411 | + }, | |
| 412 | + /** 搜索按钮操作 */ | |
| 413 | + handleQuery() { | |
| 414 | + this.queryParams.pageNo = 1; | |
| 415 | + this.getList(); | |
| 416 | + }, | |
| 417 | + /** 重置按钮操作 */ | |
| 418 | + resetQuery() { | |
| 419 | + this.dateRangeExpireTime = []; | |
| 420 | + this.dateRangeSuccessTime = []; | |
| 421 | + this.dateRangeNotifyTime = []; | |
| 422 | + this.dateRangeCreateTime = []; | |
| 423 | + this.resetForm("queryForm"); | |
| 424 | + this.handleQuery(); | |
| 425 | + }, | |
| 426 | + /** 导出按钮操作 */ | |
| 427 | + handleExport() { | |
| 428 | + // 处理查询参数 | |
| 429 | + let params = {...this.queryParams}; | |
| 430 | + params.pageNo = undefined; | |
| 431 | + params.pageSize = undefined; | |
| 432 | + this.addBeginAndEndTime(params, this.dateRangeExpireTime, 'expireTime'); | |
| 433 | + this.addBeginAndEndTime(params, this.dateRangeSuccessTime, 'successTime'); | |
| 434 | + this.addBeginAndEndTime(params, this.dateRangeNotifyTime, 'notifyTime'); | |
| 435 | + this.addDateRange(params, this.dateRangeCreateTime, 'CreateTime'); | |
| 436 | + // 执行导出 | |
| 437 | + this.$confirm('是否确认导出所有退款订单数据项?', "警告", { | |
| 438 | + confirmButtonText: "确定", | |
| 439 | + cancelButtonText: "取消", | |
| 440 | + type: "warning" | |
| 441 | + }).then(function () { | |
| 442 | + return exportRefundExcel(params); | |
| 443 | + }).then(response => { | |
| 444 | + this.downloadExcel(response, '退款订单.xls'); | |
| 445 | + }) | |
| 446 | + }, | |
| 447 | + /** | |
| 448 | + * 根据商户名称模糊匹配商户信息 | |
| 449 | + * @param name 商户名称 | |
| 450 | + */ | |
| 451 | + handleGetMerchantListByName(name) { | |
| 452 | + getMerchantListByName(name).then(response => { | |
| 453 | + this.merchantList = response.data; | |
| 454 | + this.merchantLoading = false; | |
| 455 | + }); | |
| 456 | + }, | |
| 457 | + /** | |
| 458 | + * 根据商户 ID 查询支付应用信息 | |
| 459 | + */ | |
| 460 | + handleGetAppListByMerchantId() { | |
| 461 | + this.queryParams.appId = null; | |
| 462 | + getAppListByMerchantId(this.queryParams.merchantId).then(response => { | |
| 463 | + this.appList = response.data; | |
| 464 | + }); | |
| 465 | + }, | |
| 466 | + /** | |
| 467 | + * 根据退款类别得到样式名称 | |
| 468 | + * @param refundType 退款类别 | |
| 469 | + */ | |
| 470 | + findByRefundTypeGetStyle(refundType) { | |
| 471 | + switch (refundType) { | |
| 472 | + case payOrderRefundStatusEnum.NO.status: | |
| 473 | + return "success"; | |
| 474 | + case payOrderRefundStatusEnum.SOME.status: | |
| 475 | + return "warning"; | |
| 476 | + case payOrderRefundStatusEnum.ALL.status: | |
| 477 | + return "danger"; | |
| 478 | + } | |
| 479 | + }, | |
| 480 | + /** | |
| 481 | + * 根据退款状态得到样式名称 | |
| 482 | + * @param refundStatus 退款状态 | |
| 483 | + */ | |
| 484 | + findByRefundStatusGetStyle(refundStatus) { | |
| 485 | + switch (refundStatus) { | |
| 486 | + case payRefundStatusEnum.CREATE.status: | |
| 487 | + return "info"; | |
| 488 | + case payRefundStatusEnum.SUCCESS.status: | |
| 489 | + return "success"; | |
| 490 | + case payRefundStatusEnum.FAILURE.status: | |
| 491 | + case payRefundStatusEnum.CLOSE.status: | |
| 492 | + return "danger"; | |
| 493 | + case payRefundStatusEnum.PROCESSING_NOTIFY.status: | |
| 494 | + case payRefundStatusEnum.PROCESSING_QUERY.status: | |
| 495 | + case payRefundStatusEnum.UNKNOWN_RETRY.status: | |
| 496 | + case payRefundStatusEnum.UNKNOWN_QUERY.status: | |
| 497 | + return "warning"; | |
| 498 | + } | |
| 499 | + }, | |
| 500 | + /** | |
| 501 | + * 查看订单详情 | |
| 502 | + */ | |
| 503 | + handleQueryDetails(row) { | |
| 504 | + this.refundDetail = JSON.parse(JSON.stringify(defaultRefundDetail)); | |
| 505 | + getRefund(row.id).then(response => { | |
| 506 | + this.refundDetail = response.data; | |
| 507 | + this.open = true; | |
| 508 | + }); | |
| 509 | + | |
| 510 | + }, | |
| 511 | + } | |
| 512 | +}; | |
| 513 | +</script> | |
| 514 | +<style> | |
| 515 | +.desc-label { | |
| 516 | + font-weight: bold; | |
| 517 | + | |
| 518 | +} | |
| 519 | + | |
| 520 | +.tag-purple { | |
| 521 | + color: #722ed1; | |
| 522 | + background: #f9f0ff; | |
| 523 | + border-color: #d3adf7; | |
| 524 | +} | |
| 525 | + | |
| 526 | +.tag-cyan { | |
| 527 | + color: #13c2c2; | |
| 528 | + background: #e6fffb; | |
| 529 | + border-color: #87e8de; | |
| 530 | +} | |
| 531 | + | |
| 532 | +.tag-pink { | |
| 533 | + color: #eb2f96; | |
| 534 | + background: #fff0f6; | |
| 535 | + border-color: #ffadd2; | |
| 536 | +} | |
| 537 | + | |
| 538 | +.order-font { | |
| 539 | + font-size: 12px; | |
| 540 | + padding: 2px 0; | |
| 541 | +} | |
| 542 | +</style> | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayRefundCoreConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.convert.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 5 | +import org.mapstruct.Mapper; | |
| 6 | +import org.mapstruct.Mapping; | |
| 7 | +import org.mapstruct.Mappings; | |
| 8 | +import org.mapstruct.factory.Mappers; | |
| 9 | + | |
| 10 | +@Mapper | |
| 11 | +public interface PayRefundCoreConvert { | |
| 12 | + | |
| 13 | + PayRefundCoreConvert INSTANCE = Mappers.getMapper(PayRefundCoreConvert.class); | |
| 14 | + | |
| 15 | + //TODO 太多需要处理了, 暂时不用 | |
| 16 | + @Mappings(value = { | |
| 17 | + @Mapping(source = "amount", target = "payAmount"), | |
| 18 | + @Mapping(source = "id", target = "orderId"), | |
| 19 | + @Mapping(target = "status",ignore = true) | |
| 20 | + }) | |
| 21 | + PayRefundDO convert(PayOrderDO orderDO); | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java
| ... | ... | @@ -2,6 +2,8 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | +import com.baomidou.mybatisplus.annotation.FieldFill; | |
| 6 | +import com.baomidou.mybatisplus.annotation.TableField; | |
| 5 | 7 | import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 8 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | 9 | import lombok.*; |
| ... | ... | @@ -29,6 +31,7 @@ public class PayMerchantDO extends BaseDO { |
| 29 | 31 | /** |
| 30 | 32 | * 商户号 |
| 31 | 33 | * 例如说,M233666999 |
| 34 | + * 只有新增时插入,不允许修改 | |
| 32 | 35 | */ |
| 33 | 36 | private String no; |
| 34 | 37 | /** | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderDO.java
| ... | ... | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO |
| 4 | 4 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; |
| 5 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; |
| 6 | 6 | import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; |
| 7 | -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderRefundStatusEnum; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 8 | 8 | import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; |
| 9 | 9 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 10 | 10 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| ... | ... | @@ -135,7 +135,7 @@ public class PayOrderDO extends BaseDO { |
| 135 | 135 | /** |
| 136 | 136 | * 退款状态 |
| 137 | 137 | * |
| 138 | - * 枚举 {@link PayOrderRefundStatusEnum} | |
| 138 | + * 枚举 {@link PayRefundTypeEnum} | |
| 139 | 139 | */ |
| 140 | 140 | private Integer refundStatus; |
| 141 | 141 | /** | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderExtensionDO.java
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayRefundDO.java
| ... | ... | @@ -3,9 +3,13 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order; |
| 3 | 3 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; |
| 4 | 4 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; |
| 5 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 6 | 8 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 7 | 9 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 8 | -import lombok.Data; | |
| 10 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 11 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 12 | +import lombok.*; | |
| 9 | 13 | |
| 10 | 14 | import java.util.Date; |
| 11 | 15 | |
| ... | ... | @@ -17,19 +21,21 @@ import java.util.Date; |
| 17 | 21 | * |
| 18 | 22 | * @author 芋道源码 |
| 19 | 23 | */ |
| 24 | +@TableName("pay_refund") | |
| 20 | 25 | @Data |
| 26 | +@EqualsAndHashCode(callSuper = true) | |
| 27 | +@ToString(callSuper = true) | |
| 28 | +@Builder | |
| 29 | +@NoArgsConstructor | |
| 30 | +@AllArgsConstructor | |
| 21 | 31 | public class PayRefundDO extends BaseDO { |
| 22 | 32 | |
| 23 | 33 | /** |
| 24 | 34 | * 退款单编号,数据库自增 |
| 25 | 35 | */ |
| 36 | + @TableId | |
| 26 | 37 | private Long id; |
| 27 | - /** | |
| 28 | - * 退款单号,根据规则生成 | |
| 29 | - * | |
| 30 | - * 例如说,R202109181134287570000 | |
| 31 | - */ | |
| 32 | - private String no; | |
| 38 | + | |
| 33 | 39 | /** |
| 34 | 40 | * 商户编号 |
| 35 | 41 | * |
| ... | ... | @@ -61,23 +67,48 @@ public class PayRefundDO extends BaseDO { |
| 61 | 67 | */ |
| 62 | 68 | private Long orderId; |
| 63 | 69 | |
| 70 | + /** | |
| 71 | + * 交易订单号,根据规则生成 | |
| 72 | + * 调用支付渠道时,使用该字段作为对接的订单号。 | |
| 73 | + * 1. 调用微信支付 https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 时,使用该字段作为 out_trade_no | |
| 74 | + * 2. 调用支付宝 https://opendocs.alipay.com/apis 时,使用该字段作为 out_trade_no | |
| 75 | + * 这里对应 pay_extension 里面的 no | |
| 76 | + * 例如说,P202110132239124200055 | |
| 77 | + */ | |
| 78 | + private String tradeNo; | |
| 79 | + | |
| 80 | + | |
| 64 | 81 | // ========== 商户相关字段 ========== |
| 65 | 82 | /** |
| 66 | - * 商户退款订单号 | |
| 67 | - * 例如说,内部系统 A 的退款订单号。需要保证每个 PayMerchantDO 唯一 TODO 芋艿:需要在测试下 | |
| 83 | + * 商户订单编号 | |
| 68 | 84 | */ |
| 85 | + private String merchantOrderId; | |
| 86 | + | |
| 87 | + /** | |
| 88 | + * 商户退款订单号, 由商户系统产生, 由他们保证唯一,不能为空,通知商户时会传该字段。 | |
| 89 | + * 例如说,内部系统 A 的退款订单号。需要保证每个 PayMerchantDO 唯一 | |
| 90 | + * 个商户退款订单,对应一条退款请求记录。可多次提交。 渠道保持幂等 | |
| 91 | + * 使用商户退款单,作为退款请求号 | |
| 92 | + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml 中的 out_refund_no | |
| 93 | + * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no | |
| 94 | + * 退款请求号。 | |
| 95 | + * 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。 | |
| 96 | + * 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更, | |
| 97 | + * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。 | |
| 98 | + * 退款单请求号,根据规则生成 | |
| 99 | + * 例如说,R202109181134287570000 | |
| 100 | + */ | |
| 101 | + // TODO @jason:merchantRefundNo =》merchantRefundOId | |
| 69 | 102 | private String merchantRefundNo; |
| 70 | -// /** | |
| 71 | -// * 商户拓展参数 | |
| 72 | -// */ | |
| 73 | -// private String merchantExtra; | |
| 103 | + | |
| 74 | 104 | /** |
| 75 | 105 | * 异步通知地址 |
| 76 | 106 | */ |
| 77 | 107 | private String notifyUrl; |
| 108 | + | |
| 78 | 109 | /** |
| 79 | 110 | * 通知商户退款结果的回调状态 |
| 80 | - * TODO 芋艿:0 未发送 1 已发送 | |
| 111 | + * TODO 0 未发送 1 已发送 | |
| 81 | 112 | */ |
| 82 | 113 | private Integer notifyStatus; |
| 83 | 114 | |
| ... | ... | @@ -85,44 +116,81 @@ public class PayRefundDO extends BaseDO { |
| 85 | 116 | /** |
| 86 | 117 | * 退款状态 |
| 87 | 118 | * |
| 88 | - * TODO 芋艿:状态枚举 | |
| 119 | + * 枚举 {@link PayRefundStatusEnum} | |
| 89 | 120 | */ |
| 90 | 121 | private Integer status; |
| 122 | + | |
| 91 | 123 | /** |
| 92 | - * 用户 IP | |
| 124 | + * 退款类型(部分退款,全部退款) | |
| 125 | + * | |
| 126 | + * 枚举 {@link PayRefundTypeEnum} | |
| 93 | 127 | */ |
| 94 | - private String userIp; | |
| 128 | + private Integer type; | |
| 129 | + /** | |
| 130 | + * 支付金额,单位:分 | |
| 131 | + */ | |
| 132 | + private Long payAmount; | |
| 95 | 133 | /** |
| 96 | 134 | * 退款金额,单位:分 |
| 97 | 135 | */ |
| 98 | - private Long amount; | |
| 136 | + private Long refundAmount; | |
| 137 | + | |
| 99 | 138 | /** |
| 100 | 139 | * 退款原因 |
| 101 | 140 | */ |
| 102 | 141 | private String reason; |
| 142 | + | |
| 103 | 143 | /** |
| 104 | - * 订单退款成功时间 | |
| 144 | + * 用户 IP | |
| 105 | 145 | */ |
| 106 | - private Date successTime; | |
| 146 | + private String userIp; | |
| 147 | + | |
| 148 | + // ========== 渠道相关字段 ========== | |
| 107 | 149 | /** |
| 108 | - * 退款失效时间 | |
| 150 | + * 渠道订单号,pay_order 中的channel_order_no 对应 | |
| 109 | 151 | */ |
| 110 | - private Date expireTime; | |
| 152 | + private String channelOrderNo; | |
| 153 | + /** | |
| 154 | + * 微信中的 refund_id | |
| 155 | + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml | |
| 156 | + * 支付宝没有 | |
| 157 | + * 渠道退款单号,渠道返回 | |
| 158 | + */ | |
| 159 | + private String channelRefundNo; | |
| 160 | + | |
| 161 | + /** | |
| 162 | + * 调用渠道的错误码 | |
| 163 | + */ | |
| 164 | + private String channelErrorCode; | |
| 165 | + | |
| 166 | + /** | |
| 167 | + * 调用渠道报错时,错误信息 | |
| 168 | + */ | |
| 169 | + private String channelErrorMsg; | |
| 170 | + | |
| 171 | + | |
| 111 | 172 | /** |
| 112 | 173 | * 支付渠道的额外参数 |
| 113 | - * | |
| 114 | 174 | * 参见 https://www.pingxx.com/api/Refunds%20退款概述.html |
| 115 | 175 | */ |
| 116 | - private String channelExtra; | |
| 176 | + private String channelExtras; | |
| 177 | + | |
| 117 | 178 | |
| 118 | - // ========== 渠道相关字段 ========== | |
| 119 | 179 | /** |
| 120 | - * 渠道订单号 | |
| 180 | + * TODO | |
| 181 | + * 退款失效时间 | |
| 121 | 182 | */ |
| 122 | - private String channelOrderNo; | |
| 183 | + private Date expireTime; | |
| 123 | 184 | /** |
| 124 | - * 渠道退款号 | |
| 185 | + * 退款成功时间 | |
| 125 | 186 | */ |
| 126 | - private String channelRefundNo; | |
| 187 | + private Date successTime; | |
| 188 | + /** | |
| 189 | + * 退款通知时间 | |
| 190 | + */ | |
| 191 | + private Date notifyTime; | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 127 | 195 | |
| 128 | 196 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundCoreMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import org.apache.ibatis.annotations.Mapper; | |
| 6 | + | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 退款订单 Mapper | |
| 10 | + * | |
| 11 | + */ | |
| 12 | +@Mapper | |
| 13 | +public interface PayRefundCoreMapper extends BaseMapperX<PayRefundDO> { | |
| 14 | + | |
| 15 | + default PayRefundDO selectByReqNo(String reqNo) { | |
| 16 | + return selectOne("req_no", reqNo); | |
| 17 | + } | |
| 18 | + | |
| 19 | + default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){ | |
| 20 | + return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo); | |
| 21 | + } | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java
| ... | ... | @@ -9,23 +9,56 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; |
| 9 | 9 | */ |
| 10 | 10 | public interface PayErrorCodeCoreConstants { |
| 11 | 11 | |
| 12 | - // ========== APP 模块 1-007-000-000 ========== | |
| 12 | + /** | |
| 13 | + * ========== APP 模块 1-007-000-000 ========== | |
| 14 | + */ | |
| 13 | 15 | ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在"); |
| 14 | 16 | ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用"); |
| 17 | + ErrorCode PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在交易中的订单,无法删除"); | |
| 15 | 18 | |
| 16 | - // ========== CHANNEL 模块 1-007-001-000 ========== | |
| 19 | + /** | |
| 20 | + * ========== CHANNEL 模块 1-007-001-000 ========== | |
| 21 | + */ | |
| 17 | 22 | ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在"); |
| 18 | 23 | ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); |
| 19 | 24 | ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); |
| 20 | - | |
| 21 | - // ========== ORDER 模块 1-007-002-000 ========== | |
| 25 | + ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在"); | |
| 26 | + ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道"); | |
| 27 | + ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空"); | |
| 28 | + ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001007,"微信渠道v3版本apiclient_key.pem不可为空"); | |
| 29 | + ErrorCode CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL = new ErrorCode(1007001008,"微信渠道v3版本中apiclient_cert.pem不可为空"); | |
| 30 | + ErrorCode PAY_CHANNEL_NOTIFY_VERIFY_FAILED = new ErrorCode(1007001009, "渠道通知校验失败"); | |
| 31 | + /** | |
| 32 | + * ========== ORDER 模块 1-007-002-000 ========== | |
| 33 | + */ | |
| 22 | 34 | ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); |
| 23 | 35 | ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); |
| 24 | 36 | ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); |
| 25 | 37 | ErrorCode PAY_ORDER_ERROR_USER = new ErrorCode(1007002003, "支付订单用户不正确"); |
| 26 | - // ========== ORDER 模块(拓展单) 1-007-003-000 ========== | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * ========== ORDER 模块(拓展单) 1-007-003-000 ========== | |
| 41 | + */ | |
| 27 | 42 | ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); |
| 28 | 43 | ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); |
| 29 | 44 | ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007003002, "支付订单不处于已支付"); |
| 30 | 45 | |
| 46 | + // ========== 支付模块(退款) 1-007-006-000 ========== | |
| 47 | + ErrorCode PAY_REFUND_AMOUNT_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); | |
| 48 | + ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款"); | |
| 49 | + ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空"); | |
| 50 | + ErrorCode PAY_REFUND_SUCCEED = new ErrorCode(1007006003, "已经退款成功"); | |
| 51 | + ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); | |
| 52 | + | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * ========== 支付商户信息 1-007-004-000 ========== | |
| 56 | + */ | |
| 57 | + ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); | |
| 58 | + ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除"); | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 31 | 64 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.enums.order; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Getter; | |
| 5 | + | |
| 6 | +@Getter | |
| 7 | +@AllArgsConstructor | |
| 8 | +public enum PayRefundStatusEnum { | |
| 9 | + | |
| 10 | + CREATE(0, "退款订单生成"), | |
| 11 | + SUCCESS(1, "退款成功"), | |
| 12 | + FAILURE(2, "退款失败"), | |
| 13 | + CLOSE(99, "退款关闭"); | |
| 14 | + | |
| 15 | + private final Integer status; | |
| 16 | + private final String name; | |
| 17 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderRefundStatusEnum.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundTypeEnum.java
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java
| ... | ... | @@ -5,8 +5,10 @@ import cn.hutool.http.HttpUtil; |
| 5 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyLogDO; |
| 6 | 6 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyTaskDO; |
| 7 | 7 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; |
| 8 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 8 | 9 | import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyLogCoreMapper; |
| 9 | 10 | import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyTaskCoreMapper; |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper; | |
| 10 | 12 | import cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify.PayNotifyLockCoreRedisDAO; |
| 11 | 13 | import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; |
| 12 | 14 | import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; |
| ... | ... | @@ -73,6 +75,9 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { |
| 73 | 75 | private PayNotifyLockCoreRedisDAO payNotifyLockCoreRedisDAO; |
| 74 | 76 | |
| 75 | 77 | @Resource |
| 78 | + private PayRefundCoreMapper payRefundCoreMapper; | |
| 79 | + | |
| 80 | + @Resource | |
| 76 | 81 | @Lazy // 循环依赖(自己依赖自己),避免报错 |
| 77 | 82 | private PayNotifyCoreServiceImpl self; |
| 78 | 83 | |
| ... | ... | @@ -89,7 +94,9 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { |
| 89 | 94 | setMerchantOrderId(order.getMerchantOrderId()).setNotifyUrl(order.getNotifyUrl()); |
| 90 | 95 | } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) { |
| 91 | 96 | // TODO 芋艿,需要实现下哈 |
| 92 | - throw new UnsupportedOperationException("需要实现"); | |
| 97 | + PayRefundDO refundDO = payRefundCoreMapper.selectById(task.getDataId()); | |
| 98 | + task.setMerchantId(refundDO.getMerchantId()).setAppId(refundDO.getAppId()) | |
| 99 | + .setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl()); | |
| 93 | 100 | } |
| 94 | 101 | |
| 95 | 102 | // 执行插入 | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayRefundOrderReqVO.java
| ... | ... | @@ -17,12 +17,15 @@ import javax.validation.constraints.NotNull; |
| 17 | 17 | @AllArgsConstructor |
| 18 | 18 | public class PayRefundOrderReqVO { |
| 19 | 19 | |
| 20 | - @ApiModelProperty(value = "商户订单编号", required = true, example = "10") | |
| 21 | - @NotEmpty(message = "商户订单号不能为空") | |
| 20 | + @ApiModelProperty(value = "商户退款单编号", required = true, example = "10") | |
| 21 | + @NotEmpty(message = "商户退款单编号不能为空") | |
| 22 | 22 | private String merchantOrderId; |
| 23 | 23 | |
| 24 | 24 | @ApiModelProperty(value = "支付退款编号", required = true, example = "20") |
| 25 | 25 | @NotNull(message = "支付退款编号不能为空") |
| 26 | 26 | private Long payRefundId; |
| 27 | 27 | |
| 28 | + @ApiModelProperty(value = "退款状态(成功,失败)", required = true, example = "10") | |
| 29 | + private Integer status; | |
| 30 | + | |
| 28 | 31 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreService.java
| 1 | 1 | package cn.iocoder.yudao.coreservice.modules.pay.service.order; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; |
| 4 | -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; | |
| 5 | -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; | |
| 6 | -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.*; | |
| 6 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; | |
| 7 | 7 | |
| 8 | 8 | import javax.validation.Valid; |
| 9 | 9 | |
| ... | ... | @@ -43,9 +43,8 @@ public interface PayOrderCoreService { |
| 43 | 43 | * 通知支付单成功 |
| 44 | 44 | * |
| 45 | 45 | * @param channelId 渠道编号 |
| 46 | - * @param channelCode 渠道编码 | |
| 47 | 46 | * @param notifyData 通知数据 |
| 48 | 47 | */ |
| 49 | - void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception; | |
| 48 | + void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception; | |
| 50 | 49 | |
| 51 | 50 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.service.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO; | |
| 5 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 退款单 Core Service | |
| 9 | + * | |
| 10 | + * @author jason | |
| 11 | + */ | |
| 12 | +public interface PayRefundCoreService { | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 提交退款申请 | |
| 16 | + * | |
| 17 | + * @param reqDTO 退款申请信息 | |
| 18 | + * @return 退款申请返回信息 | |
| 19 | + */ | |
| 20 | + PayRefundRespDTO submitRefundOrder(PayRefundReqDTO reqDTO); | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 渠道的退款通知 | |
| 24 | + * | |
| 25 | + * @param channelId 渠道编号 | |
| 26 | + * @param notifyData 通知数据 | |
| 27 | + * @throws Exception 退款通知异常 | |
| 28 | + */ | |
| 29 | + void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) throws Exception; | |
| 30 | + | |
| 31 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.NoArgsConstructor; | |
| 7 | +import lombok.experimental.Accessors; | |
| 8 | + | |
| 9 | +import javax.validation.constraints.DecimalMin; | |
| 10 | +import javax.validation.constraints.NotEmpty; | |
| 11 | +import javax.validation.constraints.NotNull; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 退款申请单 Request DTO | |
| 15 | + */ | |
| 16 | +@Data | |
| 17 | +@Accessors(chain = true) | |
| 18 | +@Builder | |
| 19 | +@NoArgsConstructor | |
| 20 | +@AllArgsConstructor | |
| 21 | +public class PayRefundReqDTO { | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 支付订单编号 | |
| 25 | + */ | |
| 26 | + @NotNull(message = "支付订单编号不能为空") | |
| 27 | + private Long payOrderId; | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 退款金额 | |
| 31 | + */ | |
| 32 | + @NotNull(message = "退款金额不能为空") | |
| 33 | + @DecimalMin(value = "0", inclusive = false, message = "退款金额必须大于零") | |
| 34 | + private Long amount; | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 退款原因 | |
| 38 | + */ | |
| 39 | + private String reason; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * 商户退款订单号 | |
| 43 | + */ | |
| 44 | + @NotEmpty(message = "商户退款订单号不能为空") | |
| 45 | + private String merchantRefundId; | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 用户 IP | |
| 49 | + */ | |
| 50 | + private String userIp; | |
| 51 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.NoArgsConstructor; | |
| 7 | +import lombok.experimental.Accessors; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 退款申请单 Response DTO | |
| 11 | + */ | |
| 12 | +@Data | |
| 13 | +@Accessors(chain = true) | |
| 14 | +@Builder | |
| 15 | +@NoArgsConstructor | |
| 16 | +@AllArgsConstructor | |
| 17 | +public class PayRefundRespDTO { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 支付退款单编号,自增 | |
| 21 | + */ | |
| 22 | + private Long refundId; | |
| 23 | + | |
| 24 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayOrderCoreServiceImpl.java
| ... | ... | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.date.DateUtil; |
| 4 | 4 | import cn.hutool.core.util.RandomUtil; |
| 5 | -import cn.hutool.core.util.StrUtil; | |
| 6 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.convert.order.PayOrderCoreConvert; |
| 7 | 6 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; |
| 8 | 7 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; |
| ... | ... | @@ -26,6 +25,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 26 | 25 | import cn.iocoder.yudao.framework.pay.config.PayProperties; |
| 27 | 26 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 28 | 27 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 28 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; | |
| 29 | 29 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; |
| 30 | 30 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; |
| 31 | 31 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -96,6 +96,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 96 | 96 | // 订单相关字段 |
| 97 | 97 | order.setStatus(PayOrderStatusEnum.WAITING.getStatus()); |
| 98 | 98 | // 退款相关字段 |
| 99 | + // todo @芋艿 创建支付的订单的退款状态枚举是不是有问题,应该是 PayRefundTypeEnum 吧 您这填写的是 PayOrderNotifyStatusEnum 回调状态枚举 | |
| 99 | 100 | order.setRefundStatus(PayOrderNotifyStatusEnum.NO.getStatus()) |
| 100 | 101 | .setRefundTimes(0).setRefundAmount(0L); |
| 101 | 102 | payOrderCoreMapper.insert(order); |
| ... | ... | @@ -135,9 +136,11 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 135 | 136 | // 调用三方接口 |
| 136 | 137 | PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderCoreConvert.INSTANCE.convert2(reqDTO); |
| 137 | 138 | // 商户相关字段 |
| 139 | + //TODO jason @芋艿 是否加一个属性 如tradeNo 支付订单号, 用这个merchantOrderId让人迷糊 | |
| 138 | 140 | unifiedOrderReqDTO.setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性! |
| 139 | 141 | .setSubject(order.getSubject()).setBody(order.getBody()) |
| 140 | - .setNotifyUrl(genChannelPayNotifyUrl(channel)); | |
| 142 | + .setNotifyUrl(genChannelPayNotifyUrl(channel)) | |
| 143 | + .setReturnUrl(genChannelReturnUrl(channel)); | |
| 141 | 144 | // 订单相关字段 |
| 142 | 145 | unifiedOrderReqDTO.setAmount(order.getAmount()).setExpireTime(order.getExpireTime()); |
| 143 | 146 | CommonResult<?> unifiedOrderResult = client.unifiedOrder(unifiedOrderReqDTO); |
| ... | ... | @@ -150,15 +153,23 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 150 | 153 | } |
| 151 | 154 | |
| 152 | 155 | /** |
| 156 | + * 根据支付渠道的编码,生成支付渠道的返回地址 | |
| 157 | + * @param channel 支付渠道 | |
| 158 | + * @return 支付成功返回的地址。 配置地址 + "/" + channel id | |
| 159 | + */ | |
| 160 | + private String genChannelReturnUrl(PayChannelDO channel) { | |
| 161 | + return payProperties.getPayReturnUrl() + "/" + channel.getId(); | |
| 162 | + } | |
| 163 | + | |
| 164 | + /** | |
| 153 | 165 | * 根据支付渠道的编码,生成支付渠道的回调地址 |
| 154 | 166 | * |
| 155 | 167 | * @param channel 支付渠道 |
| 156 | - * @return 支付渠道的回调地址 | |
| 168 | + * @return 支付渠道的回调地址 配置地址 + "/" + channel id | |
| 157 | 169 | */ |
| 158 | 170 | private String genChannelPayNotifyUrl(PayChannelDO channel) { |
| 159 | - // _ 转化为 - 的原因,是因为 URL 我们统一采用中划线的原则 | |
| 160 | - return payProperties.getPayNotifyUrl() + "/" + StrUtil.replace(channel.getCode(), "_", "-") | |
| 161 | - + "/" + channel.getId(); | |
| 171 | + //去掉channel code, 似乎没啥用, 用统一的回调地址 | |
| 172 | + return payProperties.getPayNotifyUrl() + "/" + channel.getId(); | |
| 162 | 173 | } |
| 163 | 174 | |
| 164 | 175 | private String generateOrderExtensionNo() { |
| ... | ... | @@ -181,9 +192,9 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 181 | 192 | |
| 182 | 193 | @Override |
| 183 | 194 | @Transactional |
| 184 | - public void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception { | |
| 195 | + public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception { | |
| 185 | 196 | // TODO 芋艿,记录回调日志 |
| 186 | - log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData); | |
| 197 | + log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); | |
| 187 | 198 | |
| 188 | 199 | // 校验支付渠道是否有效 |
| 189 | 200 | PayChannelDO channel = payChannelCoreService.validPayChannel(channelId); |
| ... | ... | @@ -193,6 +204,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 193 | 204 | log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); |
| 194 | 205 | throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); |
| 195 | 206 | } |
| 207 | + | |
| 196 | 208 | // 解析支付结果 |
| 197 | 209 | PayOrderNotifyRespDTO notifyRespDTO = client.parseOrderNotify(notifyData); |
| 198 | 210 | |
| ... | ... | @@ -207,9 +219,10 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 207 | 219 | throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); |
| 208 | 220 | } |
| 209 | 221 | // 1.2 更新 PayOrderExtensionDO |
| 222 | + //TODO 支付宝交易超时 TRADE_FINISHED 需要更新交易关闭 | |
| 210 | 223 | int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getId(), |
| 211 | 224 | PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId()) |
| 212 | - .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData).build()); | |
| 225 | + .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData.getBody()).build()); | |
| 213 | 226 | if (updateCounts == 0) { // 校验状态,必须是待支付 |
| 214 | 227 | throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); |
| 215 | 228 | } |
| ... | ... | @@ -225,7 +238,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { |
| 225 | 238 | } |
| 226 | 239 | // 2.2 更新 PayOrderDO |
| 227 | 240 | updateCounts = payOrderCoreMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), |
| 228 | - PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelId(channelId).channelCode(channelCode) | |
| 241 | + PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelId(channelId).channelCode(channel.getCode()) | |
| 229 | 242 | .successTime(notifyRespDTO.getSuccessTime()).successExtensionId(orderExtension.getId()) |
| 230 | 243 | .channelOrderNo(notifyRespDTO.getChannelOrderNo()).channelUserId(notifyRespDTO.getChannelUserId()) |
| 231 | 244 | .notifyTime(new Date()).build()); | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; | |
| 8 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; | |
| 9 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper; | |
| 10 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderExtensionCoreMapper; | |
| 11 | +import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper; | |
| 12 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; | |
| 13 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; | |
| 14 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; | |
| 15 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; | |
| 16 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 17 | +import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService; | |
| 18 | +import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService; | |
| 19 | +import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; | |
| 20 | +import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 21 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; | |
| 22 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; | |
| 23 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO; | |
| 24 | +import cn.iocoder.yudao.framework.pay.core.client.PayClient; | |
| 25 | +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | |
| 26 | +import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; | |
| 27 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; | |
| 28 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO; | |
| 29 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; | |
| 30 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; | |
| 31 | +import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum; | |
| 32 | +import lombok.extern.slf4j.Slf4j; | |
| 33 | +import org.springframework.stereotype.Service; | |
| 34 | +import org.springframework.transaction.annotation.Transactional; | |
| 35 | + | |
| 36 | +import javax.annotation.Resource; | |
| 37 | +import java.util.Date; | |
| 38 | +import java.util.Objects; | |
| 39 | + | |
| 40 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; | |
| 41 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 42 | + | |
| 43 | +@Service | |
| 44 | +@Slf4j | |
| 45 | +public class PayRefundCoreServiceImpl implements PayRefundCoreService { | |
| 46 | + | |
| 47 | + @Resource | |
| 48 | + private PayOrderCoreMapper payOrderCoreMapper; | |
| 49 | + @Resource | |
| 50 | + private PayRefundCoreMapper payRefundCoreMapper; | |
| 51 | + @Resource | |
| 52 | + private PayOrderExtensionCoreMapper payOrderExtensionCoreMapper; | |
| 53 | + | |
| 54 | + @Resource | |
| 55 | + private PayAppCoreService payAppCoreService; | |
| 56 | + @Resource | |
| 57 | + private PayChannelCoreService payChannelCoreService; | |
| 58 | + @Resource | |
| 59 | + private PayNotifyCoreService payNotifyCoreService; | |
| 60 | + | |
| 61 | + @Resource | |
| 62 | + private PayClientFactory payClientFactory; | |
| 63 | + | |
| 64 | + @Override | |
| 65 | + @Transactional(rollbackFor = Exception.class) | |
| 66 | + public PayRefundRespDTO submitRefundOrder(PayRefundReqDTO req) { | |
| 67 | + // 获得 PayOrderDO | |
| 68 | + PayOrderDO order = payOrderCoreMapper.selectById(req.getPayOrderId()); | |
| 69 | + // 校验订单是否存在 | |
| 70 | + if (Objects.isNull(order) ) { | |
| 71 | + throw exception(PAY_ORDER_NOT_FOUND); | |
| 72 | + } | |
| 73 | + // 校验 App | |
| 74 | + PayAppDO app = payAppCoreService.validPayApp(order.getAppId()); | |
| 75 | + // 校验支付渠道是否有效 | |
| 76 | + PayChannelDO channel = payChannelCoreService.validPayChannel(order.getChannelId()); | |
| 77 | + // 校验支付客户端是否正确初始化 | |
| 78 | + PayClient client = payClientFactory.getPayClient(channel.getId()); | |
| 79 | + if (client == null) { | |
| 80 | + log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); | |
| 81 | + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); | |
| 82 | + } | |
| 83 | + | |
| 84 | + // 校验退款的条件 | |
| 85 | + validatePayRefund(req, order); | |
| 86 | + // 退款类型 | |
| 87 | + PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME; | |
| 88 | + if (Objects.equals(req.getAmount(), order.getAmount())) { | |
| 89 | + refundType = PayRefundTypeEnum.ALL; | |
| 90 | + } | |
| 91 | + PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId()); | |
| 92 | + PayRefundDO payRefundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundId()); | |
| 93 | + if(Objects.nonNull(payRefundDO)){ | |
| 94 | + // 退款订单已经提交过。 | |
| 95 | + //TODO 校验相同退款单的金额 | |
| 96 | + // TODO @jason:咱要不封装一个 ObjectUtils.equalsAny | |
| 97 | + if (Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus()) | |
| 98 | + || Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())) { | |
| 99 | + //已成功退款 | |
| 100 | + throw exception(PAY_REFUND_SUCCEED); | |
| 101 | + } | |
| 102 | + //可以重复提交,保证 退款请求号 一致,由渠道保证幂等 | |
| 103 | + }else { | |
| 104 | + // 成功,插入退款单 状态为生成.没有和渠道交互 | |
| 105 | + // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; | |
| 106 | + payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo()) | |
| 107 | + .appId(order.getAppId()) | |
| 108 | + .channelOrderNo(order.getChannelOrderNo()) | |
| 109 | + .channelCode(order.getChannelCode()) | |
| 110 | + .channelId(order.getChannelId()) | |
| 111 | + .merchantId(order.getMerchantId()) | |
| 112 | + .orderId(order.getId()) | |
| 113 | + .merchantRefundNo(req.getMerchantRefundId()) | |
| 114 | + .notifyUrl(app.getRefundNotifyUrl()) | |
| 115 | + .payAmount(order.getAmount()) | |
| 116 | + .refundAmount(req.getAmount()) | |
| 117 | + .userIp(req.getUserIp()) | |
| 118 | + .merchantOrderId(order.getMerchantOrderId()) | |
| 119 | + .tradeNo(orderExtensionDO.getNo()) | |
| 120 | + .status(PayRefundStatusEnum.CREATE.getStatus()) | |
| 121 | + .reason(req.getReason()) | |
| 122 | + .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus()) | |
| 123 | + .type(refundType.getStatus()) | |
| 124 | + .build(); | |
| 125 | + payRefundCoreMapper.insert(payRefundDO); | |
| 126 | + } | |
| 127 | + // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; | |
| 128 | + PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO(); | |
| 129 | + unifiedReqDTO.setUserIp(req.getUserIp()) | |
| 130 | + .setAmount(req.getAmount()) | |
| 131 | + .setChannelOrderNo(order.getChannelOrderNo()) | |
| 132 | + .setPayTradeNo(orderExtensionDO.getNo()) | |
| 133 | + .setMerchantRefundId(req.getMerchantRefundId()) | |
| 134 | + .setReason(req.getReason()); | |
| 135 | + // 向渠道发起退款申请 | |
| 136 | + PayCommonResult<PayRefundUnifiedRespDTO> refundUnifiedResult = client.unifiedRefund(unifiedReqDTO); | |
| 137 | + // 检查是否失败,失败抛出业务异常。 | |
| 138 | + // TODO 渠道的异常记录。 | |
| 139 | + // TODO @jason:可以先打个 warn log 哈; | |
| 140 | + refundUnifiedResult.checkError(); | |
| 141 | + // 成功在 退款回调中处理 | |
| 142 | + return PayRefundRespDTO.builder().refundId(payRefundDO.getId()).build(); | |
| 143 | + } | |
| 144 | + | |
| 145 | + | |
| 146 | + @Override | |
| 147 | + @Transactional(rollbackFor = Exception.class) | |
| 148 | + public void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) { | |
| 149 | + log.info("[notifyPayRefund][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); | |
| 150 | + // 校验支付渠道是否有效 | |
| 151 | + PayChannelDO channel = payChannelCoreService.validPayChannel(channelId); | |
| 152 | + // 校验支付客户端是否正确初始化 | |
| 153 | + PayClient client = payClientFactory.getPayClient(channel.getId()); | |
| 154 | + if (client == null) { | |
| 155 | + log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); | |
| 156 | + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); | |
| 157 | + } | |
| 158 | + // 解析渠道退款通知数据, 统一处理 | |
| 159 | + PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData); | |
| 160 | + if (Objects.equals(PayNotifyRefundStatusEnum.SUCCESS,refundNotify.getStatus())){ | |
| 161 | + payRefundSuccess(refundNotify); | |
| 162 | + } else { | |
| 163 | + //TODO 支付异常, 支付宝似乎没有支付异常的通知。 | |
| 164 | + // TODO @jason:那这里可以考虑打个 error logger @芋艿 微信是否存在支付异常通知 | |
| 165 | + } | |
| 166 | + } | |
| 167 | + | |
| 168 | + private void payRefundSuccess(PayRefundNotifyDTO refundNotify) { | |
| 169 | + // 校验退款单存在 | |
| 170 | + PayRefundDO refundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo()); | |
| 171 | + if (refundDO == null) { | |
| 172 | + log.error("[payRefundSuccess][不存在 seqNo 为{} 的支付退款单]", refundNotify.getReqNo()); | |
| 173 | + throw exception(PAY_REFUND_NOT_FOUND); | |
| 174 | + } | |
| 175 | + | |
| 176 | + // 得到已退金额 | |
| 177 | + PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId()); | |
| 178 | + Long refundedAmount = payOrderDO.getRefundAmount(); | |
| 179 | + | |
| 180 | + PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS; | |
| 181 | + if(Objects.equals(payOrderDO.getAmount(), refundedAmount+ refundDO.getRefundAmount())){ | |
| 182 | + //支付金额 = 已退金额 + 本次退款金额。 | |
| 183 | + orderStatus = PayOrderStatusEnum.CLOSED; | |
| 184 | + } | |
| 185 | + // 更新支付订单 | |
| 186 | + PayOrderDO updateOrderDO = new PayOrderDO(); | |
| 187 | + updateOrderDO.setId(refundDO.getOrderId()) | |
| 188 | + .setRefundAmount(refundedAmount + refundDO.getRefundAmount()) | |
| 189 | + .setStatus(orderStatus.getStatus()) | |
| 190 | + .setRefundTimes(payOrderDO.getRefundTimes() + 1) | |
| 191 | + .setRefundStatus(refundDO.getType()); | |
| 192 | + payOrderCoreMapper.updateById(updateOrderDO); | |
| 193 | + | |
| 194 | + // 更新退款订单 | |
| 195 | + PayRefundDO updateRefundDO = new PayRefundDO(); | |
| 196 | + updateRefundDO.setId(refundDO.getId()) | |
| 197 | + .setSuccessTime(refundNotify.getRefundSuccessTime()) | |
| 198 | + .setChannelRefundNo(refundNotify.getChannelOrderNo()) | |
| 199 | + .setTradeNo(refundNotify.getTradeNo()) | |
| 200 | + .setNotifyTime(new Date()) | |
| 201 | + .setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); | |
| 202 | + payRefundCoreMapper.updateById(updateRefundDO); | |
| 203 | + | |
| 204 | + // 插入退款通知记录 | |
| 205 | + // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调 | |
| 206 | + payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | |
| 207 | + .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build()); | |
| 208 | + } | |
| 209 | + | |
| 210 | + /** | |
| 211 | + * 校验是否进行退款 | |
| 212 | + * @param req 退款申请信息 | |
| 213 | + * @param order 原始支付订单信息 | |
| 214 | + */ | |
| 215 | + private void validatePayRefund(PayRefundReqDTO req, PayOrderDO order) { | |
| 216 | + // 校验状态,必须是支付状态 | |
| 217 | + if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { | |
| 218 | + throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS); | |
| 219 | + } | |
| 220 | + // 是否已经全额退款 | |
| 221 | + if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) { | |
| 222 | + throw exception(PAY_REFUND_ALL_REFUNDED); | |
| 223 | + } | |
| 224 | + // 校验金额 退款金额不能大于 原定的金额 | |
| 225 | + if (req.getAmount() + order.getRefundAmount() > order.getAmount()){ | |
| 226 | + throw exception(PAY_REFUND_AMOUNT_EXCEED); | |
| 227 | + } | |
| 228 | + // 校验渠道订单号 | |
| 229 | + if (StrUtil.isEmpty(order.getChannelOrderNo())) { | |
| 230 | + throw exception(PAY_REFUND_CHN_ORDER_NO_IS_NULL); | |
| 231 | + } | |
| 232 | + //TODO 退款的期限 退款次数的控制 | |
| 233 | + } | |
| 234 | + | |
| 235 | +} | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/util/PaySeqUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.coreservice.modules.pay.util; | |
| 2 | + | |
| 3 | +import cn.hutool.core.date.DatePattern; | |
| 4 | +import cn.hutool.core.date.DateUtil; | |
| 5 | +import cn.hutool.core.util.RandomUtil; | |
| 6 | + | |
| 7 | +import java.util.Date; | |
| 8 | +import java.util.concurrent.atomic.AtomicLong; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 支付相关编号的生产 | |
| 12 | + */ | |
| 13 | +public class PaySeqUtils { | |
| 14 | + | |
| 15 | + private static final AtomicLong REFUND_REQ_NO_SEQ = new AtomicLong(0L); | |
| 16 | + | |
| 17 | + private static final AtomicLong MER_REFUND_NO_SEQ = new AtomicLong(0L); | |
| 18 | + | |
| 19 | + private static final AtomicLong MER_ORDER_NO_SEQ = new AtomicLong(0L); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 生成商户退款单号,用于测试,应该由商户系统生成 | |
| 23 | + * @return 商户退款单 | |
| 24 | + */ | |
| 25 | + public static String genMerchantRefundNo() { | |
| 26 | + return String.format("%s%s%04d", "MR", | |
| 27 | + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN), | |
| 28 | + (int) MER_REFUND_NO_SEQ.getAndIncrement() % 10000); | |
| 29 | + } | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 生成退款请求号 | |
| 33 | + * @return 退款请求号 | |
| 34 | + */ | |
| 35 | + public static String genRefundReqNo() { | |
| 36 | + return String.format("%s%s%04d", "RR", | |
| 37 | + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN), | |
| 38 | + (int) REFUND_REQ_NO_SEQ.getAndIncrement() % 10000); | |
| 39 | + } | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * 生成商户订单编号号 用于测试,应该由商户系统生成 | |
| 43 | + * @return 商户订单编号 | |
| 44 | + */ | |
| 45 | + public static String genMerchantOrderNo() { | |
| 46 | + return String.format("%s%s%04d", "MO", | |
| 47 | + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN), | |
| 48 | + (int) MER_ORDER_NO_SEQ.getAndIncrement() % 10000); | |
| 49 | + } | |
| 50 | +} | ... | ... |
yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapperTest.java
| ... | ... | @@ -4,6 +4,7 @@ import cn.hutool.core.io.IoUtil; |
| 4 | 4 | import cn.iocoder.yudao.coreservice.BaseDbAndRedisIntegrationTest; |
| 5 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 7 | +import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; | |
| 7 | 8 | import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; |
| 8 | 9 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 9 | 10 | import org.junit.jupiter.api.Test; |
| ... | ... | @@ -20,10 +21,10 @@ public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest { |
| 20 | 21 | private PayChannelCoreMapper payChannelCoreMapper; |
| 21 | 22 | |
| 22 | 23 | /** |
| 23 | - * 插入初始配置 | |
| 24 | + * 插入 {@link PayChannelEnum#WX_PUB} 初始配置 | |
| 24 | 25 | */ |
| 25 | 26 | @Test |
| 26 | - public void testInsert() throws FileNotFoundException { | |
| 27 | + public void testInsertWxPub() throws FileNotFoundException { | |
| 27 | 28 | PayChannelDO payChannelDO = new PayChannelDO(); |
| 28 | 29 | payChannelDO.setCode(PayChannelEnum.WX_PUB.getCode()); |
| 29 | 30 | payChannelDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| ... | ... | @@ -44,6 +45,31 @@ public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest { |
| 44 | 45 | payChannelCoreMapper.insert(payChannelDO); |
| 45 | 46 | } |
| 46 | 47 | |
| 48 | + // TODO @ouyang:Zfb 改成 AlipayQr | |
| 49 | + /** | |
| 50 | + * 插入 {@link PayChannelEnum#ALIPAY_QR} 初始配置 | |
| 51 | + */ | |
| 52 | + @Test | |
| 53 | + public void testInsertZfb() { | |
| 54 | + PayChannelDO payChannelDO = new PayChannelDO(); | |
| 55 | + payChannelDO.setCode(PayChannelEnum.ALIPAY_QR.getCode()); | |
| 56 | + payChannelDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 57 | + payChannelDO.setFeeRate(1D); | |
| 58 | + payChannelDO.setMerchantId(1L); | |
| 59 | + payChannelDO.setAppId(6L); | |
| 60 | + // 配置 | |
| 61 | + AlipayPayClientConfig config = new AlipayPayClientConfig(); | |
| 62 | + config.setAppId("2021000118634035"); | |
| 63 | + config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX); | |
| 64 | + config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT); | |
| 65 | + config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8="); | |
| 66 | + config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); | |
| 67 | + // 创建客户端 | |
| 68 | + payChannelDO.setConfig(config); | |
| 69 | + // 执行插入 | |
| 70 | + payChannelCoreMapper.insert(payChannelDO); | |
| 71 | + } | |
| 72 | + | |
| 47 | 73 | /** |
| 48 | 74 | * 查询所有支付配置,看看是否都是 ok 的 |
| 49 | 75 | */ | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml
| ... | ... | @@ -30,12 +30,8 @@ |
| 30 | 30 | |
| 31 | 31 | <!-- 工具类相关 --> |
| 32 | 32 | <dependency> |
| 33 | - <groupId>jakarta.validation</groupId> | |
| 34 | - <artifactId>jakarta.validation-api</artifactId> | |
| 35 | - </dependency> | |
| 36 | - <dependency> | |
| 37 | - <groupId>org.hibernate.validator</groupId> | |
| 38 | - <artifactId>hibernate-validator</artifactId> | |
| 33 | + <groupId>org.springframework.boot</groupId> | |
| 34 | + <artifactId>spring-boot-starter-validation</artifactId> | |
| 39 | 35 | </dependency> |
| 40 | 36 | |
| 41 | 37 | <dependency> | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java
| ... | ... | @@ -6,8 +6,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; |
| 6 | 6 | import org.springframework.validation.annotation.Validated; |
| 7 | 7 | |
| 8 | 8 | import javax.validation.constraints.NotEmpty; |
| 9 | -import javax.validation.constraints.NotNull; | |
| 10 | -import java.time.Duration; | |
| 11 | 9 | |
| 12 | 10 | @ConfigurationProperties(prefix = "yudao.pay") |
| 13 | 11 | @Validated |
| ... | ... | @@ -25,8 +23,16 @@ public class PayProperties { |
| 25 | 23 | * 退款回调地址 |
| 26 | 24 | * 注意点,同 {@link #payNotifyUrl} 属性 |
| 27 | 25 | */ |
| 28 | - @NotNull(message = "短信发送频率不能为空") | |
| 26 | + @NotEmpty(message = "退款回调地址不能为空") | |
| 29 | 27 | @URL(message = "退款回调地址的格式必须是 URL") |
| 30 | 28 | private String refundNotifyUrl; |
| 31 | 29 | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 支付完成的返回地址 | |
| 33 | + */ | |
| 34 | + @URL(message = "支付返回的地址的格式必须是 URL") | |
| 35 | + @NotEmpty(message = "支付返回的地址不能为空") | |
| 36 | + private String payReturnUrl; | |
| 37 | + | |
| 32 | 38 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
| 1 | 1 | package cn.iocoder.yudao.framework.pay.core.client; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; | |
| 4 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; | |
| 3 | + | |
| 4 | +import cn.iocoder.yudao.framework.pay.core.client.dto.*; | |
| 5 | 5 | |
| 6 | 6 | /** |
| 7 | 7 | * 支付客户端,用于对接各支付渠道的 SDK,实现发起支付、退款等功能 |
| ... | ... | @@ -32,6 +32,42 @@ public interface PayClient { |
| 32 | 32 | * @return 解析结果 |
| 33 | 33 | * @throws Exception 解析失败,抛出异常 |
| 34 | 34 | */ |
| 35 | - PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception; | |
| 35 | + PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws Exception; | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * 调用支付渠道,进行退款 | |
| 39 | + * @param reqDTO 统一退款请求信息 | |
| 40 | + * @return 各支付渠道的统一返回结果 | |
| 41 | + */ | |
| 42 | + PayCommonResult<PayRefundUnifiedRespDTO> unifiedRefund(PayRefundUnifiedReqDTO reqDTO); | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * 解析支付退款通知数据 | |
| 46 | + * @param notifyData 支付退款通知请求数据 | |
| 47 | + * @return 支付退款通知的Notify DTO | |
| 48 | + */ | |
| 49 | + PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData); | |
| 50 | + | |
| 51 | + // TODO @芋艿:后续改成非 default,避免不知道去实现 | |
| 52 | + /** | |
| 53 | + * 验证是否渠道通知 | |
| 54 | + * | |
| 55 | + * @param notifyData 通知数据 | |
| 56 | + * @return 默认是 true | |
| 57 | + */ | |
| 58 | + default boolean verifyNotifyData(PayNotifyDataDTO notifyData) { | |
| 59 | + return true; | |
| 60 | + } | |
| 61 | + | |
| 62 | + // TODO @芋艿:后续改成非 default,避免不知道去实现 | |
| 63 | + /** | |
| 64 | + * 判断是否为退款通知 | |
| 65 | + * | |
| 66 | + * @param notifyData 通知数据 | |
| 67 | + * @return 默认是 false | |
| 68 | + */ | |
| 69 | + default boolean isRefundNotify(PayNotifyDataDTO notifyData){ | |
| 70 | + return false; | |
| 71 | + } | |
| 36 | 72 | |
| 37 | 73 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java
| ... | ... | @@ -2,6 +2,11 @@ package cn.iocoder.yudao.framework.pay.core.client; |
| 2 | 2 | |
| 3 | 3 | import com.fasterxml.jackson.annotation.JsonTypeInfo; |
| 4 | 4 | |
| 5 | +import javax.validation.ConstraintViolation; | |
| 6 | +import javax.validation.ConstraintViolationException; | |
| 7 | +import javax.validation.Validator; | |
| 8 | +import java.util.Set; | |
| 9 | + | |
| 5 | 10 | /** |
| 6 | 11 | * 支付客户端的配置,本质是支付渠道的配置 |
| 7 | 12 | * 每个不同的渠道,需要不同的配置,通过子类来定义 |
| ... | ... | @@ -13,4 +18,24 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; |
| 13 | 18 | // 1. 序列化到时数据库时,增加 @class 属性。 |
| 14 | 19 | // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型 |
| 15 | 20 | public interface PayClientConfig { |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 配置验证参数是 | |
| 24 | + * | |
| 25 | + * @param validator 校验对象 | |
| 26 | + * @return 配置好的验证参数 | |
| 27 | + */ | |
| 28 | + Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator); | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 参数校验 | |
| 32 | + * | |
| 33 | + * @param validator 校验对象 | |
| 34 | + */ | |
| 35 | + default void validate(Validator validator) { | |
| 36 | + Set<ConstraintViolation<PayClientConfig>> violations = verifyParam(validator); | |
| 37 | + if (!violations.isEmpty()) { | |
| 38 | + throw new ConstraintViolationException(violations); | |
| 39 | + } | |
| 40 | + } | |
| 16 | 41 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.client.dto; | |
| 2 | + | |
| 3 | +import lombok.Builder; | |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.ToString; | |
| 6 | + | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 支付订单,退款订单回调,渠道的统一通知请求数据 | |
| 12 | + */ | |
| 13 | +@Data | |
| 14 | +@ToString | |
| 15 | +@Builder | |
| 16 | +public class PayNotifyDataDTO { | |
| 17 | + | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * HTTP 回调接口的 request body | |
| 21 | + */ | |
| 22 | + private String body; | |
| 23 | + | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数 | |
| 27 | + */ | |
| 28 | + private Map<String,String> params; | |
| 29 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderNotifyRespDTO.java
| ... | ... | @@ -42,4 +42,13 @@ public class PayOrderNotifyRespDTO { |
| 42 | 42 | */ |
| 43 | 43 | private String data; |
| 44 | 44 | |
| 45 | + /** | |
| 46 | + * TODO @jason 结合其他的渠道定义成枚举, | |
| 47 | + * alipay | |
| 48 | + * TRADE_CLOSED,未付款交易超时关闭,或支付完成后全额退款。 | |
| 49 | + * TRADE_SUCCESS, 交易支付成功 | |
| 50 | + * TRADE_FINISHED 交易结束,不可退款。 | |
| 51 | + */ | |
| 52 | + private String tradeStatus; | |
| 53 | + | |
| 45 | 54 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java
| ... | ... | @@ -44,11 +44,16 @@ public class PayOrderUnifiedReqDTO { |
| 44 | 44 | @Length(max = 128, message = "商品描述信息长度不能超过128") |
| 45 | 45 | private String body; |
| 46 | 46 | /** |
| 47 | - * 支付结果的回调地址 | |
| 47 | + * 支付结果的 notify 回调地址 | |
| 48 | 48 | */ |
| 49 | 49 | @NotEmpty(message = "支付结果的回调地址不能为空") |
| 50 | - @URL(message = "支付结果的回调地址必须是 URL 格式") | |
| 50 | + @URL(message = "支付结果的 notify 回调地址必须是 URL 格式") | |
| 51 | 51 | private String notifyUrl; |
| 52 | + /** | |
| 53 | + * 支付结果的 return 回调地址 | |
| 54 | + */ | |
| 55 | + @URL(message = "支付结果的 return 回调地址必须是 URL 格式") | |
| 56 | + private String returnUrl; | |
| 52 | 57 | |
| 53 | 58 | // ========== 订单相关字段 ========== |
| 54 | 59 | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundNotifyDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.client.dto; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.ToString; | |
| 7 | + | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 从渠道返回数据中解析得到的支付退款通知的Notify DTO | |
| 12 | + * | |
| 13 | + * @author jason | |
| 14 | + */ | |
| 15 | +@Data | |
| 16 | +@ToString | |
| 17 | +@Builder | |
| 18 | +public class PayRefundNotifyDTO { | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 支付渠道编号 | |
| 22 | + */ | |
| 23 | + private String channelOrderNo; | |
| 24 | + | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 交易订单号,根据规则生成 | |
| 28 | + * 调用支付渠道时,使用该字段作为对接的订单号。 | |
| 29 | + * 1. 调用微信支付 https://api.mch.weixin.qq.com/pay/unifiedorder 时,使用该字段作为 out_trade_no | |
| 30 | + * 2. 调用支付宝 https://opendocs.alipay.com/apis 时,使用该字段作为 out_trade_no | |
| 31 | + * 这里对应 pay_extension 里面的 no | |
| 32 | + * 例如说,P202110132239124200055 | |
| 33 | + */ | |
| 34 | + private String tradeNo; | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no | |
| 38 | + * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no | |
| 39 | + * 退款请求号。 | |
| 40 | + * 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。 | |
| 41 | + * 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更, | |
| 42 | + * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。 | |
| 43 | + * 退款单请求号,根据规则生成 | |
| 44 | + * | |
| 45 | + * 例如说,RR202109181134287570000 | |
| 46 | + */ | |
| 47 | + private String reqNo; | |
| 48 | + | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 退款是否成功 | |
| 52 | + */ | |
| 53 | + private PayNotifyRefundStatusEnum status; | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 退款成功时间 | |
| 59 | + */ | |
| 60 | + private Date refundSuccessTime; | |
| 61 | + | |
| 62 | + | |
| 63 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.client.dto; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.NoArgsConstructor; | |
| 7 | +import lombok.experimental.Accessors; | |
| 8 | +import org.hibernate.validator.constraints.URL; | |
| 9 | + | |
| 10 | +import javax.validation.constraints.DecimalMin; | |
| 11 | +import javax.validation.constraints.NotEmpty; | |
| 12 | +import javax.validation.constraints.NotNull; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 统一 退款 Request DTO | |
| 16 | + * | |
| 17 | + * @author jason | |
| 18 | + */ | |
| 19 | +@Accessors(chain = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +@Data | |
| 24 | +public class PayRefundUnifiedReqDTO { | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 用户 IP | |
| 28 | + */ | |
| 29 | + private String userIp; | |
| 30 | + | |
| 31 | + // TODO @jason:这个是否为非必传字段呀,只需要传递 payTradeNo 字段即可。尽可能精简 | |
| 32 | + /** | |
| 33 | + * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 transaction_id | |
| 34 | + * https://opendocs.alipay.com/apis alipay.trade.refund 中的 trade_no | |
| 35 | + * 渠道订单号 | |
| 36 | + */ | |
| 37 | + private String channelOrderNo; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no | |
| 41 | + * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no | |
| 42 | + * 支付交易号 {PayOrderExtensionDO no字段} 和 渠道订单号 不能同时为空 | |
| 43 | + */ | |
| 44 | + private String payTradeNo; | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no | |
| 48 | + * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no | |
| 49 | + * 退款请求单号 同一退款请求单号多次请求只退一笔。 | |
| 50 | + * 使用 商户的退款单号。{PayRefundDO 字段 merchantRefundNo} | |
| 51 | + */ | |
| 52 | + @NotEmpty(message = "退款请求单号") | |
| 53 | + private String merchantRefundId; | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * 退款原因 | |
| 57 | + */ | |
| 58 | + @NotEmpty(message = "退款原因不能为空") | |
| 59 | + private String reason; | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * 退款金额,单位:分 | |
| 63 | + */ | |
| 64 | + @NotNull(message = "退款金额不能为空") | |
| 65 | + @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") | |
| 66 | + private Long amount; | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要 | |
| 70 | + */ | |
| 71 | + @URL(message = "支付结果的 notify 回调地址必须是 URL 格式") | |
| 72 | + private String notifyUrl; | |
| 73 | + | |
| 74 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.client.dto; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import lombok.experimental.Accessors; | |
| 9 | +/** | |
| 10 | + * 统一退款 Response DTO | |
| 11 | + * | |
| 12 | + * @author jason | |
| 13 | + */ | |
| 14 | +@Accessors(chain = true) | |
| 15 | +@Builder | |
| 16 | +@NoArgsConstructor | |
| 17 | +@AllArgsConstructor | |
| 18 | +@Data | |
| 19 | +public class PayRefundUnifiedRespDTO { | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 渠道退款单编号 | |
| 23 | + */ | |
| 24 | + private String channelRefundId; | |
| 25 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
| 1 | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.extra.validation.ValidationUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | |
| 4 | 5 | import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; |
| 5 | 6 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 6 | 7 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 7 | 8 | import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; |
| 8 | 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; |
| 10 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; | |
| 11 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; | |
| 9 | 12 | import lombok.extern.slf4j.Slf4j; |
| 10 | 13 | |
| 14 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 11 | 15 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 12 | 16 | |
| 13 | 17 | /** |
| ... | ... | @@ -22,6 +26,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen |
| 22 | 26 | * 渠道编号 |
| 23 | 27 | */ |
| 24 | 28 | private final Long channelId; |
| 29 | + | |
| 25 | 30 | /** |
| 26 | 31 | * 渠道编码 |
| 27 | 32 | */ |
| ... | ... | @@ -91,7 +96,26 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen |
| 91 | 96 | return result; |
| 92 | 97 | } |
| 93 | 98 | |
| 99 | + | |
| 100 | + | |
| 94 | 101 | protected abstract PayCommonResult<?> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) |
| 95 | 102 | throws Throwable; |
| 96 | 103 | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public PayCommonResult<PayRefundUnifiedRespDTO> unifiedRefund(PayRefundUnifiedReqDTO reqDTO) { | |
| 107 | + PayCommonResult<PayRefundUnifiedRespDTO> resp; | |
| 108 | + try { | |
| 109 | + resp = doUnifiedRefund(reqDTO); | |
| 110 | + } catch (Throwable ex) { | |
| 111 | + // 记录异常日志 | |
| 112 | + log.error("[unifiedRefund][request({}) 发起退款失败]", toJsonString(reqDTO), ex); | |
| 113 | + resp = PayCommonResult.error(ex); | |
| 114 | + } | |
| 115 | + return resp; | |
| 116 | + } | |
| 117 | + | |
| 118 | + | |
| 119 | + protected abstract PayCommonResult<PayRefundUnifiedRespDTO> doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable; | |
| 120 | + | |
| 97 | 121 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java
| ... | ... | @@ -58,10 +58,15 @@ public class PayClientFactoryImpl implements PayClientFactory { |
| 58 | 58 | PayChannelEnum channelEnum = PayChannelEnum.getByCode(channelCode); |
| 59 | 59 | Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelEnum)); |
| 60 | 60 | // 创建客户端 |
| 61 | + // TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 | |
| 61 | 62 | switch (channelEnum) { |
| 62 | 63 | case WX_PUB: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config); |
| 64 | + case WX_LITE: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config); | |
| 65 | + case WX_APP: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config); | |
| 63 | 66 | case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); |
| 64 | 67 | case ALIPAY_QR: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); |
| 68 | + case ALIPAY_APP: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); | |
| 69 | + case ALIPAY_PC: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); | |
| 65 | 70 | } |
| 66 | 71 | // 创建失败,错误日志 + 抛出异常 |
| 67 | 72 | log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", config); | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | |
| 2 | + | |
| 3 | +import cn.hutool.core.bean.BeanUtil; | |
| 4 | +import cn.hutool.core.date.DateUtil; | |
| 5 | +import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; | |
| 6 | +import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; | |
| 7 | +import cn.iocoder.yudao.framework.pay.core.client.dto.*; | |
| 8 | +import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; | |
| 9 | +import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum; | |
| 10 | +import com.alipay.api.AlipayApiException; | |
| 11 | +import com.alipay.api.AlipayConfig; | |
| 12 | +import com.alipay.api.DefaultAlipayClient; | |
| 13 | +import com.alipay.api.domain.AlipayTradeRefundModel; | |
| 14 | +import com.alipay.api.internal.util.AlipaySignature; | |
| 15 | +import com.alipay.api.request.AlipayTradeRefundRequest; | |
| 16 | +import com.alipay.api.response.AlipayTradeRefundResponse; | |
| 17 | +import lombok.SneakyThrows; | |
| 18 | +import lombok.extern.slf4j.Slf4j; | |
| 19 | + | |
| 20 | +import java.nio.charset.StandardCharsets; | |
| 21 | +import java.util.Map; | |
| 22 | + | |
| 23 | +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | |
| 24 | + | |
| 25 | +/** | |
| 26 | + * 支付宝抽象类, 实现支付宝统一的接口。如退款 | |
| 27 | + * | |
| 28 | + * @author jason | |
| 29 | + */ | |
| 30 | +@Slf4j | |
| 31 | +public abstract class AbstractAlipayClient extends AbstractPayClient<AlipayPayClientConfig> { | |
| 32 | + | |
| 33 | + protected DefaultAlipayClient client; | |
| 34 | + | |
| 35 | + public AbstractAlipayClient(Long channelId, String channelCode, | |
| 36 | + AlipayPayClientConfig config, AbstractPayCodeMapping codeMapping) { | |
| 37 | + super(channelId, channelCode, config, codeMapping); | |
| 38 | + } | |
| 39 | + | |
| 40 | + @Override | |
| 41 | + @SneakyThrows | |
| 42 | + protected void doInit() { | |
| 43 | + AlipayConfig alipayConfig = new AlipayConfig(); | |
| 44 | + BeanUtil.copyProperties(config, alipayConfig, false); | |
| 45 | + this.client = new DefaultAlipayClient(alipayConfig); | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 从支付宝通知返回参数中解析 PayOrderNotifyRespDTO, 通知具体参数参考 | |
| 50 | + * //https://opendocs.alipay.com/open/203/105286 | |
| 51 | + * @param data 通知结果 | |
| 52 | + * @return 解析结果 PayOrderNotifyRespDTO | |
| 53 | + * @throws Exception 解析失败,抛出异常 | |
| 54 | + */ | |
| 55 | + @Override | |
| 56 | + public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws Exception { | |
| 57 | + Map<String, String> params = data.getParams(); | |
| 58 | + return PayOrderNotifyRespDTO.builder().orderExtensionNo(params.get("out_trade_no")) | |
| 59 | + .channelOrderNo(params.get("trade_no")).channelUserId(params.get("seller_id")) | |
| 60 | + .tradeStatus(params.get("trade_status")) | |
| 61 | + .successTime(DateUtil.parse(params.get("notify_time"), "yyyy-MM-dd HH:mm:ss")) | |
| 62 | + .data(data.getBody()).build(); | |
| 63 | + } | |
| 64 | + | |
| 65 | + @Override | |
| 66 | + public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) { | |
| 67 | + Map<String, String> params = notifyData.getParams(); | |
| 68 | + PayRefundNotifyDTO notifyDTO = PayRefundNotifyDTO.builder().channelOrderNo(params.get("trade_no")) | |
| 69 | + .tradeNo(params.get("out_trade_no")) | |
| 70 | + .reqNo(params.get("out_biz_no")) | |
| 71 | + .status(PayNotifyRefundStatusEnum.SUCCESS) | |
| 72 | + .refundSuccessTime(DateUtil.parse(params.get("gmt_refund"), "yyyy-MM-dd HH:mm:ss")) | |
| 73 | + .build(); | |
| 74 | + return notifyDTO; | |
| 75 | + } | |
| 76 | + | |
| 77 | + @Override | |
| 78 | + public boolean isRefundNotify(PayNotifyDataDTO notifyData) { | |
| 79 | + if (notifyData.getParams().containsKey("refund_fee")) { | |
| 80 | + return true; | |
| 81 | + } else { | |
| 82 | + return false; | |
| 83 | + } | |
| 84 | + } | |
| 85 | + | |
| 86 | + @Override | |
| 87 | + public boolean verifyNotifyData(PayNotifyDataDTO notifyData) { | |
| 88 | + boolean verifyResult = false; | |
| 89 | + try { | |
| 90 | + verifyResult = AlipaySignature.rsaCheckV1(notifyData.getParams(), config.getAlipayPublicKey(), StandardCharsets.UTF_8.name(), "RSA2"); | |
| 91 | + } catch (AlipayApiException e) { | |
| 92 | + log.error("[AlipayClient verifyNotifyData][(notify param is :{}) 验证失败]", toJsonString(notifyData.getParams()), e); | |
| 93 | + } | |
| 94 | + return verifyResult; | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * 支付宝统一的退款接口 alipay.trade.refund | |
| 99 | + * @param reqDTO 退款请求 request DTO | |
| 100 | + * @return 退款请求 Response | |
| 101 | + */ | |
| 102 | + @Override | |
| 103 | + protected PayCommonResult<PayRefundUnifiedRespDTO> doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { | |
| 104 | + AlipayTradeRefundModel model=new AlipayTradeRefundModel(); | |
| 105 | + model.setTradeNo(reqDTO.getChannelOrderNo()); | |
| 106 | + model.setOutTradeNo(reqDTO.getPayTradeNo()); | |
| 107 | + model.setOutRequestNo(reqDTO.getMerchantRefundId()); | |
| 108 | + model.setRefundAmount(calculateAmount(reqDTO.getAmount()).toString()); | |
| 109 | + model.setRefundReason(reqDTO.getReason()); | |
| 110 | + AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest(); | |
| 111 | + refundRequest.setBizModel(model); | |
| 112 | + try { | |
| 113 | + AlipayTradeRefundResponse response = client.execute(refundRequest); | |
| 114 | + log.info("[doUnifiedRefund][response({}) 发起退款 渠道返回", toJsonString(response)); | |
| 115 | + if (response.isSuccess()) { | |
| 116 | + //退款导致触发的异步通知是发送到支付接口中设置的notify_url | |
| 117 | + //支付宝不返回退款单号,设置为空 | |
| 118 | + PayRefundUnifiedRespDTO respDTO = new PayRefundUnifiedRespDTO(); | |
| 119 | + respDTO.setChannelRefundId(""); | |
| 120 | + return PayCommonResult.build(response.getCode(), response.getMsg(), respDTO, codeMapping); | |
| 121 | + } | |
| 122 | + // 失败。需要抛出异常 | |
| 123 | + return PayCommonResult.build(response.getCode(), response.getMsg(), null, codeMapping); | |
| 124 | + } catch (AlipayApiException e) { | |
| 125 | + // TODO 记录异常日志 | |
| 126 | + log.error("[doUnifiedRefund][request({}) 发起退款失败,网络读超时,退款状态未知]", toJsonString(reqDTO), e); | |
| 127 | + return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); | |
| 128 | + } | |
| 129 | + } | |
| 130 | + | |
| 131 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java
| ... | ... | @@ -3,7 +3,14 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; |
| 3 | 3 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | +import javax.validation.ConstraintViolation; | |
| 7 | +import javax.validation.Validator; | |
| 8 | +import javax.validation.constraints.NotBlank; | |
| 9 | +import javax.validation.constraints.NotNull; | |
| 10 | +import java.util.Set; | |
| 11 | + | |
| 6 | 12 | // TODO 芋艿:参数校验 |
| 13 | + | |
| 7 | 14 | /** |
| 8 | 15 | * 支付宝的 PayClientConfig 实现类 |
| 9 | 16 | * 属性主要来自 {@link com.alipay.api.AlipayConfig} 的必要属性 |
| ... | ... | @@ -25,11 +32,11 @@ public class AlipayPayClientConfig implements PayClientConfig { |
| 25 | 32 | /** |
| 26 | 33 | * 公钥类型 - 公钥模式 |
| 27 | 34 | */ |
| 28 | - private static final Integer MODE_PUBLIC_KEY = 1; | |
| 35 | + public static final Integer MODE_PUBLIC_KEY = 1; | |
| 29 | 36 | /** |
| 30 | 37 | * 公钥类型 - 证书模式 |
| 31 | 38 | */ |
| 32 | - private static final Integer MODE_CERTIFICATE = 2; | |
| 39 | + public static final Integer MODE_CERTIFICATE = 2; | |
| 33 | 40 | |
| 34 | 41 | /** |
| 35 | 42 | * 签名算法类型 - RSA |
| ... | ... | @@ -41,18 +48,21 @@ public class AlipayPayClientConfig implements PayClientConfig { |
| 41 | 48 | * 1. {@link #SERVER_URL_PROD} |
| 42 | 49 | * 2. {@link #SERVER_URL_SANDBOX} |
| 43 | 50 | */ |
| 51 | + @NotBlank(message = "网关地址不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) | |
| 44 | 52 | private String serverUrl; |
| 45 | 53 | |
| 46 | 54 | /** |
| 47 | 55 | * 开放平台上创建的应用的 ID |
| 48 | 56 | */ |
| 57 | + @NotBlank(message = "开放平台上创建的应用的 ID不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) | |
| 49 | 58 | private String appId; |
| 50 | 59 | |
| 51 | 60 | /** |
| 52 | 61 | * 签名算法类型,推荐:RSA2 |
| 53 | - * | |
| 62 | + * <p> | |
| 54 | 63 | * {@link #SIGN_TYPE_DEFAULT} |
| 55 | 64 | */ |
| 65 | + @NotBlank(message = "签名算法类型不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) | |
| 56 | 66 | private String signType; |
| 57 | 67 | |
| 58 | 68 | /** |
| ... | ... | @@ -60,30 +70,48 @@ public class AlipayPayClientConfig implements PayClientConfig { |
| 60 | 70 | * 1. {@link #MODE_PUBLIC_KEY} 情况,privateKey + alipayPublicKey |
| 61 | 71 | * 2. {@link #MODE_CERTIFICATE} 情况,appCertContent + alipayPublicCertContent + rootCertContent |
| 62 | 72 | */ |
| 73 | + @NotNull(message = "公钥类型不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) | |
| 63 | 74 | private Integer mode; |
| 64 | 75 | |
| 65 | 76 | // ========== 公钥模式 ========== |
| 66 | 77 | /** |
| 67 | 78 | * 商户私钥 |
| 68 | 79 | */ |
| 80 | + @NotBlank(message = "商户私钥不能为空", groups = {ModePublicKey.class}) | |
| 69 | 81 | private String privateKey; |
| 82 | + | |
| 70 | 83 | /** |
| 71 | 84 | * 支付宝公钥字符串 |
| 72 | 85 | */ |
| 86 | + @NotBlank(message = "支付宝公钥字符串不能为空", groups = {ModePublicKey.class}) | |
| 73 | 87 | private String alipayPublicKey; |
| 74 | 88 | |
| 75 | 89 | // ========== 证书模式 ========== |
| 76 | 90 | /** |
| 77 | 91 | * 指定商户公钥应用证书内容字符串 |
| 78 | 92 | */ |
| 93 | + @NotBlank(message = "指定商户公钥应用证书内容不能为空", groups = {ModeCertificate.class}) | |
| 79 | 94 | private String appCertContent; |
| 80 | 95 | /** |
| 81 | 96 | * 指定支付宝公钥证书内容字符串 |
| 82 | 97 | */ |
| 98 | + @NotBlank(message = "指定支付宝公钥证书内容不能为空", groups = {ModeCertificate.class}) | |
| 83 | 99 | private String alipayPublicCertContent; |
| 84 | 100 | /** |
| 85 | 101 | * 指定根证书内容字符串 |
| 86 | 102 | */ |
| 103 | + @NotBlank(message = "指定根证书内容字符串不能为空", groups = {ModeCertificate.class}) | |
| 87 | 104 | private String rootCertContent; |
| 88 | 105 | |
| 106 | + public interface ModePublicKey { | |
| 107 | + } | |
| 108 | + | |
| 109 | + public interface ModeCertificate { | |
| 110 | + } | |
| 111 | + | |
| 112 | + @Override | |
| 113 | + public Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator) { | |
| 114 | + return validator.validate(this, | |
| 115 | + MODE_PUBLIC_KEY.equals(this.getMode()) ? ModePublicKey.class : ModeCertificate.class); | |
| 116 | + } | |
| 89 | 117 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayCodeMapping.java
| ... | ... | @@ -18,6 +18,10 @@ public class AlipayPayCodeMapping extends AbstractPayCodeMapping { |
| 18 | 18 | if (Objects.equals(apiCode, "10000")) { |
| 19 | 19 | return GlobalErrorCodeConstants.SUCCESS; |
| 20 | 20 | } |
| 21 | + // alipay wap api code 返回为null, 暂时定为-9999 | |
| 22 | + if (Objects.equals(apiCode, "-9999")) { | |
| 23 | + return GlobalErrorCodeConstants.SUCCESS; | |
| 24 | + } | |
| 21 | 25 | return null; |
| 22 | 26 | } |
| 23 | 27 | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
| 1 | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.bean.BeanUtil; | |
| 4 | 3 | import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; |
| 5 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; | |
| 6 | 4 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; |
| 7 | -import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; | |
| 8 | 5 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 9 | 6 | import com.alipay.api.AlipayApiException; |
| 10 | -import com.alipay.api.AlipayConfig; | |
| 11 | -import com.alipay.api.DefaultAlipayClient; | |
| 12 | 7 | import com.alipay.api.domain.AlipayTradePrecreateModel; |
| 13 | 8 | import com.alipay.api.request.AlipayTradePrecreateRequest; |
| 14 | 9 | import com.alipay.api.response.AlipayTradePrecreateResponse; |
| 15 | -import lombok.SneakyThrows; | |
| 16 | 10 | import lombok.extern.slf4j.Slf4j; |
| 17 | 11 | |
| 18 | 12 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| ... | ... | @@ -24,24 +18,13 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString |
| 24 | 18 | * @author 芋道源码 |
| 25 | 19 | */ |
| 26 | 20 | @Slf4j |
| 27 | -public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig> { | |
| 28 | - | |
| 29 | - private DefaultAlipayClient client; | |
| 21 | +public class AlipayQrPayClient extends AbstractAlipayClient { | |
| 30 | 22 | |
| 31 | 23 | public AlipayQrPayClient(Long channelId, AlipayPayClientConfig config) { |
| 32 | 24 | super(channelId, PayChannelEnum.ALIPAY_QR.getCode(), config, new AlipayPayCodeMapping()); |
| 33 | 25 | } |
| 34 | 26 | |
| 35 | 27 | @Override |
| 36 | - @SneakyThrows | |
| 37 | - protected void doInit() { | |
| 38 | - AlipayConfig alipayConfig = new AlipayConfig(); | |
| 39 | - BeanUtil.copyProperties(config, alipayConfig, false); | |
| 40 | - // 真实客户端 | |
| 41 | - this.client = new DefaultAlipayClient(alipayConfig); | |
| 42 | - } | |
| 43 | - | |
| 44 | - @Override | |
| 45 | 28 | public PayCommonResult<AlipayTradePrecreateResponse> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 46 | 29 | // 构建 AlipayTradePrecreateModel 请求 |
| 47 | 30 | AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); |
| ... | ... | @@ -53,7 +36,8 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig> |
| 53 | 36 | // 构建 AlipayTradePrecreateRequest |
| 54 | 37 | AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); |
| 55 | 38 | request.setBizModel(model); |
| 56 | - | |
| 39 | + request.setNotifyUrl(reqDTO.getNotifyUrl()); | |
| 40 | + request.setReturnUrl(reqDTO.getReturnUrl()); | |
| 57 | 41 | // 执行请求 |
| 58 | 42 | AlipayTradePrecreateResponse response; |
| 59 | 43 | try { |
| ... | ... | @@ -65,10 +49,4 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig> |
| 65 | 49 | // TODO 芋艿:sub Code 需要测试下各种失败的情况 |
| 66 | 50 | return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping); |
| 67 | 51 | } |
| 68 | - | |
| 69 | - @Override | |
| 70 | - public PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception { | |
| 71 | - // TODO 芋艿:待完成 | |
| 72 | - return null; | |
| 73 | - } | |
| 74 | 52 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
| 1 | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.bean.BeanUtil; | |
| 3 | +import cn.hutool.core.date.DateUtil; | |
| 4 | 4 | import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; |
| 5 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; | |
| 6 | 5 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; |
| 7 | -import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; | |
| 8 | 6 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 9 | 7 | import com.alipay.api.AlipayApiException; |
| 10 | -import com.alipay.api.AlipayConfig; | |
| 11 | -import com.alipay.api.DefaultAlipayClient; | |
| 12 | 8 | import com.alipay.api.domain.AlipayTradeWapPayModel; |
| 13 | 9 | import com.alipay.api.request.AlipayTradeWapPayRequest; |
| 14 | 10 | import com.alipay.api.response.AlipayTradeWapPayResponse; |
| 15 | -import lombok.SneakyThrows; | |
| 11 | +import lombok.extern.slf4j.Slf4j; | |
| 12 | + | |
| 13 | +import java.util.Objects; | |
| 16 | 14 | |
| 17 | 15 | /** |
| 18 | 16 | * 支付宝【手机网站】的 PayClient 实现类 |
| ... | ... | @@ -20,23 +18,15 @@ import lombok.SneakyThrows; |
| 20 | 18 | * |
| 21 | 19 | * @author 芋道源码 |
| 22 | 20 | */ |
| 23 | -public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig> { | |
| 21 | +@Slf4j | |
| 22 | +public class AlipayWapPayClient extends AbstractAlipayClient { | |
| 24 | 23 | |
| 25 | - private DefaultAlipayClient client; | |
| 26 | 24 | |
| 27 | 25 | public AlipayWapPayClient(Long channelId, AlipayPayClientConfig config) { |
| 28 | 26 | super(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), config, new AlipayPayCodeMapping()); |
| 29 | 27 | } |
| 30 | 28 | |
| 31 | 29 | @Override |
| 32 | - @SneakyThrows | |
| 33 | - protected void doInit() { | |
| 34 | - AlipayConfig alipayConfig = new AlipayConfig(); | |
| 35 | - BeanUtil.copyProperties(config, alipayConfig, false); | |
| 36 | - this.client = new DefaultAlipayClient(alipayConfig); | |
| 37 | - } | |
| 38 | - | |
| 39 | - @Override | |
| 40 | 30 | public PayCommonResult<AlipayTradeWapPayResponse> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 41 | 31 | // 构建 AlipayTradeWapPayModel 请求 |
| 42 | 32 | AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); |
| ... | ... | @@ -45,11 +35,17 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig> |
| 45 | 35 | model.setBody(reqDTO.getBody()); |
| 46 | 36 | model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString()); |
| 47 | 37 | model.setProductCode("QUICK_WAP_PAY"); // TODO 芋艿:这里咋整 |
| 48 | - model.setSellerId("2088102147948060"); // TODO 芋艿:这里咋整 | |
| 49 | - // TODO 芋艿:userIp + expireTime | |
| 38 | + //TODO 芋艿:这里咋整 jason @芋艿 可以去掉吧, | |
| 39 | + // TODO 芋艿 似乎这里不用传sellerId | |
| 40 | + // https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay | |
| 41 | + //model.setSellerId("2088102147948060"); | |
| 42 | + model.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(),"yyyy-MM-dd HH:mm:ss")); | |
| 43 | + // TODO 芋艿:userIp | |
| 50 | 44 | // 构建 AlipayTradeWapPayRequest |
| 51 | 45 | AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); |
| 52 | 46 | request.setBizModel(model); |
| 47 | + request.setNotifyUrl(reqDTO.getNotifyUrl()); | |
| 48 | + request.setReturnUrl(reqDTO.getReturnUrl()); | |
| 53 | 49 | |
| 54 | 50 | // 执行请求 |
| 55 | 51 | AlipayTradeWapPayResponse response; |
| ... | ... | @@ -58,13 +54,22 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig> |
| 58 | 54 | } catch (AlipayApiException e) { |
| 59 | 55 | return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); |
| 60 | 56 | } |
| 61 | -// TODO 芋艿:sub Code | |
| 62 | - return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping); | |
| 63 | - } | |
| 64 | 57 | |
| 65 | - @Override | |
| 66 | - public PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception { | |
| 67 | - // TODO 芋艿:待完成 | |
| 68 | - return null; | |
| 58 | + // TODO 芋艿:sub Code | |
| 59 | + if(response.isSuccess() && Objects.isNull(response.getCode()) && Objects.nonNull(response.getBody())){ | |
| 60 | + //成功alipay wap 成功 code 为 null , body 为form 表单 | |
| 61 | + return PayCommonResult.build("-9999", "Success", response, codeMapping); | |
| 62 | + }else { | |
| 63 | + return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping); | |
| 64 | + } | |
| 69 | 65 | } |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 70 | 75 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPayClientConfig.java
| ... | ... | @@ -4,10 +4,15 @@ import cn.hutool.core.io.IoUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 5 | 5 | import lombok.Data; |
| 6 | 6 | |
| 7 | +import javax.validation.ConstraintViolation; | |
| 8 | +import javax.validation.Validator; | |
| 9 | +import javax.validation.constraints.NotBlank; | |
| 7 | 10 | import java.io.FileInputStream; |
| 8 | 11 | import java.io.FileNotFoundException; |
| 12 | +import java.util.Set; | |
| 9 | 13 | |
| 10 | 14 | // TODO 芋艿:参数校验 |
| 15 | + | |
| 11 | 16 | /** |
| 12 | 17 | * 微信支付的 PayClientConfig 实现类 |
| 13 | 18 | * 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性 |
| ... | ... | @@ -20,13 +25,11 @@ public class WXPayClientConfig implements PayClientConfig { |
| 20 | 25 | // TODO 芋艿:V2 or V3 客户端 |
| 21 | 26 | /** |
| 22 | 27 | * API 版本 - V2 |
| 23 | - * | |
| 24 | 28 | * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 |
| 25 | 29 | */ |
| 26 | 30 | public static final String API_VERSION_V2 = "v2"; |
| 27 | 31 | /** |
| 28 | 32 | * API 版本 - V3 |
| 29 | - * | |
| 30 | 33 | * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml |
| 31 | 34 | */ |
| 32 | 35 | public static final String API_VERSION_V3 = "v3"; |
| ... | ... | @@ -34,14 +37,17 @@ public class WXPayClientConfig implements PayClientConfig { |
| 34 | 37 | /** |
| 35 | 38 | * 公众号或者小程序的 appid |
| 36 | 39 | */ |
| 40 | + @NotBlank(message = "APPID 不能为空", groups = {V2.class, V3.class}) | |
| 37 | 41 | private String appId; |
| 38 | 42 | /** |
| 39 | 43 | * 商户号 |
| 40 | 44 | */ |
| 45 | + @NotBlank(message = "商户号 不能为空", groups = {V2.class, V3.class}) | |
| 41 | 46 | private String mchId; |
| 42 | 47 | /** |
| 43 | 48 | * API 版本 |
| 44 | 49 | */ |
| 50 | + @NotBlank(message = "API 版本 不能为空", groups = {V2.class, V3.class}) | |
| 45 | 51 | private String apiVersion; |
| 46 | 52 | |
| 47 | 53 | // ========== V2 版本的参数 ========== |
| ... | ... | @@ -49,39 +55,59 @@ public class WXPayClientConfig implements PayClientConfig { |
| 49 | 55 | /** |
| 50 | 56 | * 商户密钥 |
| 51 | 57 | */ |
| 58 | + @NotBlank(message = "商户密钥 不能为空", groups = V2.class) | |
| 52 | 59 | private String mchKey; |
| 53 | -// /** | |
| 54 | -// * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. | |
| 55 | -// * 对应的字符串 | |
| 56 | -// * | |
| 57 | -// * 注意,可通过 {@link #main(String[])} 读取 | |
| 58 | -// */ | |
| 59 | -// private String keyContent; | |
| 60 | + /** | |
| 61 | + * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. | |
| 62 | + * 对应的字符串 | |
| 63 | + * | |
| 64 | + * 注意,可通过 {@link #main(String[])} 读取 | |
| 65 | + */ | |
| 66 | + /// private String keyContent; | |
| 60 | 67 | |
| 61 | 68 | // ========== V3 版本的参数 ========== |
| 62 | 69 | /** |
| 63 | 70 | * apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. |
| 64 | 71 | * 对应的字符串 |
| 65 | - * | |
| 66 | 72 | * 注意,可通过 {@link #main(String[])} 读取 |
| 67 | 73 | */ |
| 74 | + @NotBlank(message = "apiclient_key 不能为空", groups = V3.class) | |
| 68 | 75 | private String privateKeyContent; |
| 69 | 76 | /** |
| 70 | 77 | * apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. |
| 71 | 78 | * 对应的字符串 |
| 72 | - * | |
| 79 | + * <p> | |
| 73 | 80 | * 注意,可通过 {@link #main(String[])} 读取 |
| 74 | 81 | */ |
| 82 | + @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class) | |
| 75 | 83 | private String privateCertContent; |
| 76 | 84 | /** |
| 77 | 85 | * apiV3 秘钥值 |
| 78 | 86 | */ |
| 87 | + @NotBlank(message = "apiV3 秘钥值 不能为空", groups = V3.class) | |
| 79 | 88 | private String apiV3Key; |
| 80 | 89 | |
| 90 | + /** | |
| 91 | + * 分组校验 v2版本 | |
| 92 | + */ | |
| 93 | + public interface V2 { | |
| 94 | + } | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * 分组校验 v3版本 | |
| 98 | + */ | |
| 99 | + public interface V3 { | |
| 100 | + } | |
| 101 | + | |
| 102 | + @Override | |
| 103 | + public Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator) { | |
| 104 | + return validator.validate(this, this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class); | |
| 105 | + } | |
| 106 | + | |
| 81 | 107 | public static void main(String[] args) throws FileNotFoundException { |
| 82 | 108 | String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12"; |
| 83 | -// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem"; | |
| 84 | -// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem"; | |
| 109 | + /// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem"; | |
| 110 | + /// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem"; | |
| 85 | 111 | System.out.println(IoUtil.readUtf8(new FileInputStream(path))); |
| 86 | 112 | } |
| 87 | 113 | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java
| ... | ... | @@ -8,8 +8,7 @@ import cn.hutool.core.util.StrUtil; |
| 8 | 8 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; |
| 9 | 9 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 10 | 10 | import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; |
| 11 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; | |
| 12 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; | |
| 11 | +import cn.iocoder.yudao.framework.pay.core.client.dto.*; | |
| 13 | 12 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |
| 14 | 13 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 15 | 14 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| ... | ... | @@ -91,6 +90,7 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> { |
| 91 | 90 | return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping); |
| 92 | 91 | } |
| 93 | 92 | |
| 93 | + | |
| 94 | 94 | private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |
| 95 | 95 | // 构建 WxPayUnifiedOrderRequest 对象 |
| 96 | 96 | WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() |
| ... | ... | @@ -131,14 +131,27 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> { |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | @Override |
| 134 | - public PayOrderNotifyRespDTO parseOrderNotify(String data) throws WxPayException { | |
| 135 | - WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data); | |
| 134 | + public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws WxPayException { | |
| 135 | + WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody()); | |
| 136 | 136 | Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS"); |
| 137 | 137 | // 转换结果 |
| 138 | 138 | return PayOrderNotifyRespDTO.builder().orderExtensionNo(notifyResult.getOutTradeNo()) |
| 139 | 139 | .channelOrderNo(notifyResult.getTransactionId()).channelUserId(notifyResult.getOpenid()) |
| 140 | 140 | .successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) |
| 141 | - .data(data).build(); | |
| 141 | + .data(data.getBody()).build(); | |
| 142 | + } | |
| 143 | + | |
| 144 | + @Override | |
| 145 | + public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) { | |
| 146 | + //TODO 需要实现 | |
| 147 | + throw new UnsupportedOperationException("需要实现"); | |
| 148 | + } | |
| 149 | + | |
| 150 | + | |
| 151 | + @Override | |
| 152 | + protected PayCommonResult<PayRefundUnifiedRespDTO> doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable { | |
| 153 | + //TODO 需要实现 | |
| 154 | + throw new UnsupportedOperationException(); | |
| 142 | 155 | } |
| 143 | 156 | |
| 144 | 157 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java
| 1 | 1 | package cn.iocoder.yudao.framework.pay.core.enums; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; | |
| 5 | +import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; | |
| 6 | +import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; | |
| 4 | 7 | import lombok.AllArgsConstructor; |
| 5 | 8 | import lombok.Getter; |
| 6 | 9 | |
| ... | ... | @@ -14,18 +17,21 @@ import lombok.Getter; |
| 14 | 17 | @AllArgsConstructor |
| 15 | 18 | public enum PayChannelEnum { |
| 16 | 19 | |
| 17 | - WX_PUB("wx_pub", "微信 JSAPI 支付"), // 公众号的网页 | |
| 18 | - WX_LITE("wx_lit","微信小程序支付"), | |
| 19 | - WX_APP("wx_app", "微信 App 支付"), | |
| 20 | + /** | |
| 21 | + * 公众号网页 | |
| 22 | + */ | |
| 23 | + WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class), | |
| 24 | + WX_LITE("wx_lite", "微信小程序支付", WXPayClientConfig.class), | |
| 25 | + WX_APP("wx_app", "微信 App 支付", WXPayClientConfig.class), | |
| 20 | 26 | |
| 21 | - ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付"), | |
| 22 | - ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付"), | |
| 23 | - ALIPAY_APP("alipay_app", "支付宝App 支付"), | |
| 24 | - ALIPAY_QR("alipay_qr", "支付宝扫码支付"); | |
| 27 | + ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付", AlipayPayClientConfig.class), | |
| 28 | + ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付", AlipayPayClientConfig.class), | |
| 29 | + ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class), | |
| 30 | + ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class); | |
| 25 | 31 | |
| 26 | 32 | /** |
| 27 | 33 | * 编码 |
| 28 | - * | |
| 34 | + * <p> | |
| 29 | 35 | * 参考 https://www.pingxx.com/api/支付渠道属性值.html |
| 30 | 36 | */ |
| 31 | 37 | private String code; |
| ... | ... | @@ -34,8 +40,24 @@ public enum PayChannelEnum { |
| 34 | 40 | */ |
| 35 | 41 | private String name; |
| 36 | 42 | |
| 43 | + /** | |
| 44 | + * 配置类 | |
| 45 | + */ | |
| 46 | + private Class<? extends PayClientConfig> configClass; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 微信支付 | |
| 50 | + */ | |
| 51 | + public static final String WECHAT = "WECHAT"; | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 支付宝支付 | |
| 55 | + */ | |
| 56 | + public static final String ALIPAY = "ALIPAY"; | |
| 57 | + | |
| 37 | 58 | public static PayChannelEnum getByCode(String code) { |
| 38 | 59 | return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); |
| 39 | 60 | } |
| 61 | + | |
| 40 | 62 | |
| 41 | 63 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelRefundRespEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.enums; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Getter; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 渠道统一的退款返回结果 | |
| 8 | + * | |
| 9 | + * @author jason | |
| 10 | + */ | |
| 11 | +@Getter | |
| 12 | +@AllArgsConstructor | |
| 13 | +public enum PayChannelRefundRespEnum { | |
| 14 | + | |
| 15 | + SUCCESS(1, "退款成功"), | |
| 16 | + FAILURE(2, "退款失败"), | |
| 17 | + PROCESSING(3,"退款处理中"), | |
| 18 | + CLOSED(4, "退款关闭"); | |
| 19 | + | |
| 20 | + private final Integer status; | |
| 21 | + private final String name; | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayNotifyRefundStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.enums; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 退款通知, 统一的渠道退款状态 | |
| 5 | + * | |
| 6 | + * @author jason | |
| 7 | + */ | |
| 8 | +public enum PayNotifyRefundStatusEnum { | |
| 9 | + /** | |
| 10 | + * 支付宝 中 全额退款 trade_status=TRADE_CLOSED, 部分退款 trade_status=TRADE_SUCCESS | |
| 11 | + * 退款成功 | |
| 12 | + */ | |
| 13 | + SUCCESS, | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 支付宝退款通知没有这个状态 | |
| 17 | + * 退款异常 | |
| 18 | + */ | |
| 19 | + ABNORMAL; | |
| 20 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test-integration/java/cn/iocoder/yudao/framework/core/client/impl/PayClientFactoryImplTest.java
| ... | ... | @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient |
| 13 | 13 | import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; |
| 14 | 14 | import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient; |
| 15 | 15 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 16 | +import com.alipay.api.response.AlipayTradePrecreateResponse; | |
| 16 | 17 | import org.junit.jupiter.api.Test; |
| 17 | 18 | |
| 18 | 19 | import java.io.FileInputStream; |
| ... | ... | @@ -75,6 +76,7 @@ public class PayClientFactoryImplTest { |
| 75 | 76 | * {@link AlipayQrPayClient} |
| 76 | 77 | */ |
| 77 | 78 | @Test |
| 79 | + @SuppressWarnings("unchecked") | |
| 78 | 80 | public void testCreatePayClient_ALIPAY_QR() { |
| 79 | 81 | // 创建配置 |
| 80 | 82 | AlipayPayClientConfig config = new AlipayPayClientConfig(); |
| ... | ... | @@ -89,8 +91,10 @@ public class PayClientFactoryImplTest { |
| 89 | 91 | PayClient client = payClientFactory.getPayClient(channelId); |
| 90 | 92 | // 发起支付 |
| 91 | 93 | PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); |
| 92 | - CommonResult<?> result = client.unifiedOrder(reqDTO); | |
| 94 | + reqDTO.setNotifyUrl("http://niubi.natapp1.cc/api/pay/order/notify/alipay-qr/1"); // TODO @tina: 这里改成你的 natapp 回调地址 | |
| 95 | + CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO); | |
| 93 | 96 | System.out.println(JsonUtils.toJsonString(result)); |
| 97 | + System.out.println(result.getData().getQrCode()); | |
| 94 | 98 | } |
| 95 | 99 | |
| 96 | 100 | /** | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | |
| 2 | +import cn.hutool.core.util.ReflectUtil; | |
| 3 | +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | |
| 4 | +import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; | |
| 5 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; | |
| 6 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | |
| 7 | +import com.alipay.api.AlipayApiException; | |
| 8 | +import com.alipay.api.DefaultAlipayClient; | |
| 9 | +import com.alipay.api.request.AlipayTradePrecreateRequest; | |
| 10 | +import com.alipay.api.response.AlipayTradePrecreateResponse; | |
| 11 | +import org.junit.jupiter.api.Disabled; | |
| 12 | +import org.junit.jupiter.api.Test; | |
| 13 | +import org.mockito.ArgumentMatcher; | |
| 14 | +import org.mockito.InjectMocks; | |
| 15 | +import org.mockito.Mock; | |
| 16 | + | |
| 17 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 18 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 19 | +import static org.junit.jupiter.api.Assertions.assertNotSame; | |
| 20 | +import static org.mockito.ArgumentMatchers.argThat; | |
| 21 | +import static org.mockito.Mockito.when; | |
| 22 | + | |
| 23 | +public class AlipayQrPayClientTest extends BaseMockitoUnitTest { | |
| 24 | + | |
| 25 | + private final AlipayPayClientConfig config = new AlipayPayClientConfig() | |
| 26 | + .setAppId("2021000118634035") | |
| 27 | + .setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX) | |
| 28 | + .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT) | |
| 29 | + // TODO @tina:key 可以随机就好,简洁一点哈。 | |
| 30 | + .setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJ" + | |
| 31 | + "v890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T" + | |
| 32 | + "01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH" + | |
| 33 | + "6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScw" + | |
| 34 | + "lSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63tr" + | |
| 35 | + "epo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdk" + | |
| 36 | + "USmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr" + | |
| 37 | + "8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w" + | |
| 38 | + "0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENi" + | |
| 39 | + "vAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPw" + | |
| 40 | + "YcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQO" + | |
| 41 | + "LFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsm" + | |
| 42 | + "yX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i9" + | |
| 43 | + "5Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOU" + | |
| 44 | + "hVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD" + | |
| 45 | + "/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v1" + | |
| 46 | + "8p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ" + | |
| 47 | + "8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4e" + | |
| 48 | + "N0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6p" + | |
| 49 | + "bKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erx" + | |
| 50 | + "TRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=") | |
| 51 | + .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0" + | |
| 52 | + "gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBN" + | |
| 53 | + "lrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZ" + | |
| 54 | + "ikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); | |
| 55 | + | |
| 56 | + // TODO @tina:= 前后要有空格哈 | |
| 57 | + @InjectMocks | |
| 58 | + AlipayQrPayClient client=new AlipayQrPayClient(10L,config); | |
| 59 | + | |
| 60 | + @Mock | |
| 61 | + private DefaultAlipayClient defaultAlipayClient; | |
| 62 | + | |
| 63 | + @Test | |
| 64 | + public void testDoInit(){ | |
| 65 | + client.doInit(); | |
| 66 | + assertNotSame(defaultAlipayClient, ReflectUtil.getFieldValue(client, "defaultAlipayClient")); | |
| 67 | + } | |
| 68 | + | |
| 69 | + @Test | |
| 70 | + @Disabled // TODO 芋艿:临时禁用 | |
| 71 | + public void create() throws AlipayApiException { | |
| 72 | + // TODO @tina:参数可以尽量随机一点,使用随机方法。这样的好处是,避免对固定参数的依赖,导致可能仅仅满足固定参数的结果 | |
| 73 | + // 这里,设置可以直接随机整个对象。 | |
| 74 | + Long shopOrderId = System.currentTimeMillis(); | |
| 75 | + PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO(); | |
| 76 | + reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); | |
| 77 | + reqDTO.setAmount(1L); | |
| 78 | + reqDTO.setBody("内容:" + shopOrderId); | |
| 79 | + reqDTO.setSubject("标题:"+shopOrderId); | |
| 80 | + String notify="http://niubi.natapp1.cc/api/pay/order/notify"; | |
| 81 | + reqDTO.setNotifyUrl(notify); | |
| 82 | + | |
| 83 | + AlipayTradePrecreateResponse response=randomPojo(AlipayTradePrecreateResponse.class,o->o.setQrCode("success")); | |
| 84 | + | |
| 85 | + when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request ->{ | |
| 86 | + assertEquals(notify,request.getNotifyUrl()); | |
| 87 | + return true; | |
| 88 | + }))).thenReturn(response); | |
| 89 | + | |
| 90 | + | |
| 91 | + PayCommonResult<AlipayTradePrecreateResponse> result = client.doUnifiedOrder(reqDTO); | |
| 92 | + // 断言 | |
| 93 | + assertEquals(response.getCode(), result.getApiCode()); | |
| 94 | + assertEquals(response.getMsg(), result.getApiMsg()); | |
| 95 | + // TODO @tina:这个断言木有过? | |
| 96 | + assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); | |
| 97 | + assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); | |
| 98 | + | |
| 99 | + } | |
| 100 | +} | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java
| ... | ... | @@ -4,7 +4,8 @@ import org.springframework.boot.SpringApplication; |
| 4 | 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| 5 | 5 | |
| 6 | 6 | @SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} 和 ${yudao.core-service.base-package} |
| 7 | -@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"})public class UserServerApplication { | |
| 7 | +@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"}) | |
| 8 | +public class UserServerApplication { | |
| 8 | 9 | |
| 9 | 10 | public static void main(String[] args) { |
| 10 | 11 | SpringApplication.run(UserServerApplication.class, args); | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java
| ... | ... | @@ -3,10 +3,13 @@ package cn.iocoder.yudao.userserver.modules.pay.controller.order; |
| 3 | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | 4 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; |
| 5 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; | |
| 6 | 7 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; |
| 7 | 8 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; |
| 8 | 9 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 9 | -import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | |
| 10 | +import cn.iocoder.yudao.framework.pay.core.client.PayClient; | |
| 11 | +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | |
| 12 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; | |
| 10 | 13 | import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO; |
| 11 | 14 | import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO; |
| 12 | 15 | import io.swagger.annotations.Api; |
| ... | ... | @@ -16,7 +19,10 @@ import org.springframework.validation.annotation.Validated; |
| 16 | 19 | import org.springframework.web.bind.annotation.*; |
| 17 | 20 | |
| 18 | 21 | import javax.annotation.Resource; |
| 22 | +import java.util.Map; | |
| 19 | 23 | |
| 24 | +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_CLIENT_NOT_FOUND; | |
| 25 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 20 | 26 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 21 | 27 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; |
| 22 | 28 | |
| ... | ... | @@ -29,6 +35,12 @@ public class PayOrderController { |
| 29 | 35 | |
| 30 | 36 | @Resource |
| 31 | 37 | private PayOrderCoreService payOrderCoreService; |
| 38 | + @Resource | |
| 39 | + private PayRefundCoreService payRefundCoreService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private PayClientFactory payClientFactory; | |
| 43 | + | |
| 32 | 44 | |
| 33 | 45 | @PostMapping("/submit") |
| 34 | 46 | @ApiOperation("提交支付订单") |
| ... | ... | @@ -49,12 +61,61 @@ public class PayOrderController { |
| 49 | 61 | } |
| 50 | 62 | |
| 51 | 63 | // ========== 支付渠道的回调 ========== |
| 52 | - | |
| 64 | + //TODO 芋道源码 换成了统一的地址了 /notify/{channelId},测试通过可以删除 | |
| 53 | 65 | @PostMapping("/notify/wx-pub/{channelId}") |
| 54 | - @ApiOperation("通知微信公众号的结果") | |
| 66 | + @ApiOperation("通知微信公众号支付的结果") | |
| 55 | 67 | public String notifyWxPayOrder(@PathVariable("channelId") Long channelId, |
| 56 | 68 | @RequestBody String xmlData) throws Exception { |
| 57 | - payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.WX_PUB.getCode(), xmlData); | |
| 69 | + payOrderCoreService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().body(xmlData).build()); | |
| 70 | + return "success"; | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 统一的跳转页面, 支付宝跳转参数说明 | |
| 75 | + * https://opendocs.alipay.com/open/203/105285#%E5%89%8D%E5%8F%B0%E5%9B%9E%E8%B7%B3%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E | |
| 76 | + * @param channelId 渠道id | |
| 77 | + * @return 返回跳转页面 | |
| 78 | + */ | |
| 79 | + @GetMapping(value = "/return/{channelId}") | |
| 80 | + @ApiOperation("渠道统一的支付成功返回地址") | |
| 81 | + public String returnAliPayOrder(@PathVariable("channelId") Long channelId, @RequestParam Map<String, String> params){ | |
| 82 | + //TODO 可以根据渠道和 app_id 返回不同的页面 | |
| 83 | + log.info("app_id is {}", params.get("app_id")); | |
| 84 | + return String.format("渠道[%s]支付成功", channelId); | |
| 85 | + } | |
| 86 | + | |
| 87 | + /** | |
| 88 | + * 统一的渠道支付回调,支付宝的退款回调 | |
| 89 | + * | |
| 90 | + * @param channelId 渠道编号 | |
| 91 | + * @param params form 参数 | |
| 92 | + * @param originData http request body | |
| 93 | + * @return 成功返回 "success" | |
| 94 | + */ | |
| 95 | + @PostMapping(value = "/notify/{channelId}") | |
| 96 | + @ApiOperation("渠道统一的支付成功,或退款成功 通知url") | |
| 97 | + public String notifyChannelPay(@PathVariable("channelId") Long channelId, | |
| 98 | + @RequestParam Map<String, String> params, | |
| 99 | + @RequestBody String originData) throws Exception { | |
| 100 | + // 校验支付渠道是否存在 | |
| 101 | + PayClient payClient = payClientFactory.getPayClient(channelId); | |
| 102 | + if (payClient == null) { | |
| 103 | + log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId); | |
| 104 | + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); | |
| 105 | + } | |
| 106 | + | |
| 107 | + // 校验通知数据是否合法 | |
| 108 | + PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build(); | |
| 109 | + payClient.verifyNotifyData(notifyData); | |
| 110 | + | |
| 111 | + // 如果是退款,则发起退款通知 | |
| 112 | + if (payClient.isRefundNotify(notifyData)) { | |
| 113 | + payRefundCoreService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); | |
| 114 | + return "success"; | |
| 115 | + } | |
| 116 | + | |
| 117 | + // 如果非退款,则发起支付通知 | |
| 118 | + payOrderCoreService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); | |
| 58 | 119 | return "success"; |
| 59 | 120 | } |
| 60 | 121 | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.userserver.modules.pay.controller.order; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; | |
| 5 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; | |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.util.PaySeqUtils; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 8 | +import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayRefundReqVO; | |
| 9 | +import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayRefundRespVO; | |
| 10 | +import cn.iocoder.yudao.userserver.modules.pay.convert.order.PayRefundConvert; | |
| 11 | +import io.swagger.annotations.Api; | |
| 12 | +import io.swagger.annotations.ApiOperation; | |
| 13 | +import lombok.extern.slf4j.Slf4j; | |
| 14 | +import org.springframework.validation.annotation.Validated; | |
| 15 | +import org.springframework.web.bind.annotation.PostMapping; | |
| 16 | +import org.springframework.web.bind.annotation.RequestBody; | |
| 17 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 18 | +import org.springframework.web.bind.annotation.RestController; | |
| 19 | + | |
| 20 | +import javax.annotation.Resource; | |
| 21 | + | |
| 22 | +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; | |
| 23 | + | |
| 24 | +@Api(tags = "退款订单") | |
| 25 | +@RestController | |
| 26 | +@RequestMapping("/pay/order") | |
| 27 | +@Validated | |
| 28 | +@Slf4j | |
| 29 | +public class PayRefundController { | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private PayRefundCoreService payRefundCoreService; | |
| 33 | + | |
| 34 | + @PostMapping("/refund") | |
| 35 | + @ApiOperation("提交退款订单") | |
| 36 | + public CommonResult<PayRefundRespVO> submitRefundOrder(@RequestBody PayRefundReqVO reqVO){ | |
| 37 | + PayRefundReqDTO req = PayRefundConvert.INSTANCE.convert(reqVO); | |
| 38 | + req.setUserIp(getClientIP()); | |
| 39 | + //TODO 测试暂时模拟生成商户退款订单 | |
| 40 | + if(StrUtil.isEmpty(reqVO.getMerchantRefundId())) { | |
| 41 | + req.setMerchantRefundId(PaySeqUtils.genMerchantRefundNo()); | |
| 42 | + } | |
| 43 | + return CommonResult.success( PayRefundConvert.INSTANCE.convert(payRefundCoreService.submitRefundOrder(req))); | |
| 44 | + } | |
| 45 | + | |
| 46 | +} | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.userserver.modules.pay.controller.order.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.AllArgsConstructor; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | + | |
| 9 | +import javax.validation.constraints.NotEmpty; | |
| 10 | + | |
| 11 | +@ApiModel("退款订单 Req VO") | |
| 12 | +@Data | |
| 13 | +@NoArgsConstructor | |
| 14 | +@AllArgsConstructor | |
| 15 | +public class PayRefundReqVO { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "支付订单编号自增", required = true, example = "10") | |
| 18 | + @NotEmpty(message = "支付订单编号自增") | |
| 19 | + private Long payOrderId; | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "退款金额", required = true, example = "1") | |
| 22 | + @NotEmpty(message = "退款金额") | |
| 23 | + private Long amount; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "退款原因", required = true, example = "不喜欢") | |
| 26 | + @NotEmpty(message = "退款原因") | |
| 27 | + private String reason; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "商户退款订单号", required = true, example = "MR202111180000000001") | |
| 30 | + //TODO 测试暂时模拟生成 | |
| 31 | + //@NotEmpty(message = "商户退款订单号") | |
| 32 | + private String merchantRefundId; | |
| 33 | + | |
| 34 | +} | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.userserver.modules.pay.controller.order.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import lombok.experimental.Accessors; | |
| 9 | + | |
| 10 | +@ApiModel("提交退款订单 Response VO") | |
| 11 | +@Data | |
| 12 | +@Accessors(chain = true) | |
| 13 | +@Builder | |
| 14 | +@NoArgsConstructor | |
| 15 | +@AllArgsConstructor | |
| 16 | +public class PayRefundRespVO { | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 支付退款单编号, 自增 | |
| 20 | + */ | |
| 21 | + private Long refundId; | |
| 22 | +} | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/convert/order/PayRefundConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.userserver.modules.pay.convert.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; | |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO; | |
| 5 | +import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayRefundReqVO; | |
| 6 | +import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayRefundRespVO; | |
| 7 | +import org.mapstruct.Mapper; | |
| 8 | +import org.mapstruct.factory.Mappers; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 支付退款 Convert | |
| 12 | + * | |
| 13 | + * @author jason | |
| 14 | + */ | |
| 15 | +@Mapper | |
| 16 | +public interface PayRefundConvert { | |
| 17 | + | |
| 18 | + PayRefundConvert INSTANCE = Mappers.getMapper(PayRefundConvert.class); | |
| 19 | + | |
| 20 | + PayRefundReqDTO convert(PayRefundReqVO reqVO); | |
| 21 | + | |
| 22 | + PayRefundRespVO convert(PayRefundRespDTO req); | |
| 23 | +} | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/convert/package-info.java
0 → 100644
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
0 → 100644
| 1 | +<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao> | ... | ... |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/ShopOrderController.java
| 1 | 1 | package cn.iocoder.yudao.userserver.modules.shop.controller; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayNotifyOrderReqVO; |
| 4 | +import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayRefundOrderReqVO; | |
| 4 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; |
| 5 | 6 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.util.PaySeqUtils; | |
| 6 | 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 7 | 9 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; |
| 8 | 10 | import cn.iocoder.yudao.userserver.modules.shop.controller.vo.ShopOrderCreateRespVO; |
| ... | ... | @@ -43,10 +45,10 @@ public class ShopOrderController { |
| 43 | 45 | PayOrderCreateReqDTO reqDTO = new PayOrderCreateReqDTO(); |
| 44 | 46 | reqDTO.setAppId(6L); |
| 45 | 47 | reqDTO.setUserIp(getClientIP()); |
| 46 | - reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); | |
| 48 | + reqDTO.setMerchantOrderId(PaySeqUtils.genMerchantOrderNo()); | |
| 47 | 49 | reqDTO.setSubject("标题:" + shopOrderId); |
| 48 | 50 | reqDTO.setBody("内容:" + shopOrderId); |
| 49 | - reqDTO.setAmount(1); // 单位:分 | |
| 51 | + reqDTO.setAmount(200); // 单位:分 | |
| 50 | 52 | reqDTO.setExpireTime(DateUtils.addTime(Duration.ofDays(1))); |
| 51 | 53 | Long payOrderId = payOrderCoreService.createPayOrder(reqDTO); |
| 52 | 54 | |
| ... | ... | @@ -62,4 +64,11 @@ public class ShopOrderController { |
| 62 | 64 | return success(true); |
| 63 | 65 | } |
| 64 | 66 | |
| 67 | + @PostMapping("/refund-notify") | |
| 68 | + @ApiOperation("退款回调") | |
| 69 | + public CommonResult<Boolean> refundNotify(@RequestBody @Valid PayRefundOrderReqVO reqVO) { | |
| 70 | + log.info("[refundNotify][回调成功]"); | |
| 71 | + return success(true); | |
| 72 | + } | |
| 73 | + | |
| 65 | 74 | } | ... | ... |
yudao-user-server/src/main/resources/application-local.yaml
| ... | ... | @@ -158,8 +158,9 @@ yudao: |
| 158 | 158 | - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 |
| 159 | 159 | demo: false # 关闭演示模式 |
| 160 | 160 | pay: |
| 161 | - pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify | |
| 162 | - refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify | |
| 161 | + pay-notify-url: http://jg6rde.natappfree.cc/api/pay/order/notify | |
| 162 | + refund-notify-url: http://jg6rde.natappfree.cc/api/pay/refund/notify | |
| 163 | + pay-return-url: http://jg6rde.natappfree.cc/api/pay/order/return | |
| 163 | 164 | |
| 164 | 165 | justauth: |
| 165 | 166 | enabled: true | ... | ... |
yudao-user-server/src/main/resources/static/pay_alipay_qr.html
0 → 100644
| 1 | +<!DOCTYPE html> | |
| 2 | +<html> | |
| 3 | +<head> | |
| 4 | + <meta charset="UTF-8"> | |
| 5 | + <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/> | |
| 6 | + <title>支付测试页</title> | |
| 7 | + <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> | |
| 8 | + <script src="qrcode.min.js" type="text/javascript"></script> | |
| 9 | + | |
| 10 | +</head> | |
| 11 | +<body> | |
| 12 | +<div>点击如下按钮,发起支付宝扫码支付的测试</div> | |
| 13 | +<div> | |
| 14 | + <button id="alipay_wap">支付宝扫码支付</button> | |
| 15 | +</div> | |
| 16 | +<div id="qrcode"></div> | |
| 17 | +</body> | |
| 18 | +<style> | |
| 19 | + #qrcode{ | |
| 20 | + padding-left: 20px; | |
| 21 | + padding-top: 20px; | |
| 22 | + } | |
| 23 | +</style> | |
| 24 | +<script> | |
| 25 | + let shopOrderId = undefined; | |
| 26 | + let payOrderId = undefined; | |
| 27 | + let server = 'http://127.0.0.1:28080'; | |
| 28 | + $(function() { | |
| 29 | + // 自动发起商城订单编号 | |
| 30 | + $.ajax({ | |
| 31 | + url: server + "/api/shop/order/create", | |
| 32 | + method: 'POST', | |
| 33 | + success: function( result ) { | |
| 34 | + if (result.code !== 0) { | |
| 35 | + alert('创建商城订单失败,原因:' + result.msg) | |
| 36 | + return; | |
| 37 | + } | |
| 38 | + shopOrderId = result.data.id; | |
| 39 | + payOrderId = result.data.payOrderId; | |
| 40 | + console.log("商城订单:" + shopOrderId) | |
| 41 | + console.log("支付订单:" + payOrderId) | |
| 42 | + } | |
| 43 | + }) | |
| 44 | + }); | |
| 45 | + // 支付宝扫码支付 | |
| 46 | + $( "#alipay_wap").on( "click", function() { | |
| 47 | + // 提交支付 | |
| 48 | + $.ajax({ | |
| 49 | + url: server + "/api/pay/order/submit", | |
| 50 | + method: 'POST', | |
| 51 | + dataType: "json", | |
| 52 | + contentType: "application/json", | |
| 53 | + data: JSON.stringify({ | |
| 54 | + "id": payOrderId, | |
| 55 | + "channelCode": 'alipay_qr' | |
| 56 | + }), | |
| 57 | + success: function( result ) { | |
| 58 | + if (result.code !== 0) { | |
| 59 | + alert('提交支付订单失败,原因:' + result.msg) | |
| 60 | + return; | |
| 61 | + } | |
| 62 | + //提交支付后返回的参数 | |
| 63 | + let data = result.data.invokeResponse; | |
| 64 | + new QRCode($("#qrcode")[0],{ | |
| 65 | + text: data.qrCode, //内容 | |
| 66 | + width:98, //宽度 | |
| 67 | + height:98, //高度 | |
| 68 | + correctLevel: 3,//二维码纠错级别 | |
| 69 | + background: "#ffffff",//背景颜色 | |
| 70 | + foreground: "#000000"//二维码颜色 | |
| 71 | + }); | |
| 72 | + | |
| 73 | + console.log("data.qrCode===",data.qrCode) | |
| 74 | + | |
| 75 | + } | |
| 76 | + }) | |
| 77 | + }); | |
| 78 | +</script> | |
| 79 | +</html> | ... | ... |
yudao-user-server/src/main/resources/static/pay_alipay_wap.html
0 → 100644
| 1 | +<!DOCTYPE html> | |
| 2 | +<html> | |
| 3 | +<head> | |
| 4 | + <meta charset="UTF-8"> | |
| 5 | + <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/> | |
| 6 | + <title>支付测试页</title> | |
| 7 | + <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> | |
| 8 | +</head> | |
| 9 | +<body> | |
| 10 | +<div>点击如下按钮,发起支付的测试</div> | |
| 11 | +<div> | |
| 12 | + <button id="alipay_wap">支付宝手机网站支付</button> | |
| 13 | +</div> | |
| 14 | +<div id="dynamic_form"></div> | |
| 15 | +</body> | |
| 16 | +<script> | |
| 17 | + | |
| 18 | + let shopOrderId = undefined; | |
| 19 | + let payOrderId = undefined; | |
| 20 | + let server = 'http://127.0.0.1:28080'; | |
| 21 | + //let server = 'http://niubi.natapp1.cc'; | |
| 22 | + | |
| 23 | + $(function() { | |
| 24 | + // 自动发起商城订单编号 | |
| 25 | + $.ajax({ | |
| 26 | + url: server + "/api/shop/order/create", | |
| 27 | + method: 'POST', | |
| 28 | + success: function( result ) { | |
| 29 | + if (result.code !== 0) { | |
| 30 | + alert('创建商城订单失败,原因:' + result.msg) | |
| 31 | + return; | |
| 32 | + } | |
| 33 | + shopOrderId = result.data.id; | |
| 34 | + payOrderId = result.data.payOrderId; | |
| 35 | + console.log("商城订单:" + shopOrderId) | |
| 36 | + console.log("支付订单:" + payOrderId) | |
| 37 | + } | |
| 38 | + }) | |
| 39 | + }); | |
| 40 | + | |
| 41 | + $( "#alipay_wap").on( "click", function() { | |
| 42 | + // 提交支付 | |
| 43 | + $.ajax({ | |
| 44 | + url: server + "/api/pay/order/submit", | |
| 45 | + method: 'POST', | |
| 46 | + dataType: "json", | |
| 47 | + contentType: "application/json", | |
| 48 | + data: JSON.stringify({ | |
| 49 | + "id": payOrderId, | |
| 50 | + "channelCode": 'alipay_wap' | |
| 51 | + }), | |
| 52 | + success: function( result ) { | |
| 53 | + if (result.code !== 0) { | |
| 54 | + alert('提交支付订单失败,原因:' + result.msg) | |
| 55 | + return; | |
| 56 | + } | |
| 57 | + alert('点击确定,开始支付'); | |
| 58 | + //支付宝 手机WAP 返回表单,自动跳到支付宝支付页面 | |
| 59 | + let data = result.data.invokeResponse; | |
| 60 | + $("#dynamic_form").html(data.body); | |
| 61 | + } | |
| 62 | + }) | |
| 63 | + }); | |
| 64 | +</script> | |
| 65 | +</html> | ... | ... |
yudao-user-server/src/main/resources/static/pay.html renamed to yudao-user-server/src/main/resources/static/pay_wx_pub.html
yudao-user-server/src/main/resources/static/qrcode.min.js
0 → 100644
| 1 | +var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c<a.length&&0==a[c];)c++;this.num=new Array(a.length-c+b);for(var d=0;d<a.length-c;d++)this.num[d]=a[d+c]}function j(a,b){this.totalCount=a,this.dataCount=b}function k(){this.buffer=[],this.length=0}function m(){return"undefined"!=typeof CanvasRenderingContext2D}function n(){var a=!1,b=navigator.userAgent;return/android/i.test(b)&&(a=!0,aMat=b.toString().match(/android ([0-9]\.[0-9])/i),aMat&&aMat[1]&&(a=parseFloat(aMat[1]))),a}function r(a,b){for(var c=1,e=s(a),f=0,g=l.length;g>=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=new Array(this.moduleCount);for(var e=0;e<this.moduleCount;e++)this.modules[d][e]=null}this.setupPositionProbePattern(0,0),this.setupPositionProbePattern(this.moduleCount-7,0),this.setupPositionProbePattern(0,this.moduleCount-7),this.setupPositionAdjustPattern(),this.setupTimingPattern(),this.setupTypeInfo(a,c),this.typeNumber>=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f<this.modules.length;f++)for(var g=f*e,h=0;h<this.modules[f].length;h++){var i=h*e,j=this.modules[f][h];j&&(d.beginFill(0,100),d.moveTo(i,g),d.lineTo(i+e,g),d.lineTo(i+e,g+e),d.lineTo(i,g+e),d.endFill())}return d},setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(var b=8;b<this.moduleCount-8;b++)null==this.modules[6][b]&&(this.modules[6][b]=0==b%2)},setupPositionAdjustPattern:function(){for(var a=f.getPatternPosition(this.typeNumber),b=0;b<a.length;b++)for(var c=0;c<a.length;c++){var d=a[b],e=a[c];if(null==this.modules[d][e])for(var g=-2;2>=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g<a.length&&(j=1==(1&a[g]>>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h<d.length;h++){var i=d[h];g.put(i.mode,4),g.put(i.getLength(),f.getLengthInBits(i.mode,a)),i.write(g)}for(var l=0,h=0;h<e.length;h++)l+=e[h].dataCount;if(g.getLengthInBits()>8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j<b.length;j++){var k=b[j].dataCount,l=b[j].totalCount-k;d=Math.max(d,k),e=Math.max(e,l),g[j]=new Array(k);for(var m=0;m<g[j].length;m++)g[j][m]=255&a.buffer[m+c];c+=k;var n=f.getErrorCorrectPolynomial(l),o=new i(g[j],n.getLength()-1),p=o.mod(n);h[j]=new Array(n.getLength()-1);for(var m=0;m<h[j].length;m++){var q=m+p.getLength()-h[j].length;h[j][m]=q>=0?p.get(q):0}}for(var r=0,m=0;m<b.length;m++)r+=b[m].totalCount;for(var s=new Array(r),t=0,m=0;d>m;m++)for(var j=0;j<b.length;j++)m<g[j].length&&(s[t++]=g[j][m]);for(var m=0;e>m;m++)for(var j=0;j<b.length;j++)m<h[j].length&&(s[t++]=h[j][m]);return s};for(var c={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},d={L:1,M:0,Q:3,H:2},e={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},f={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var b=a<<10;f.getBCHDigit(b)-f.getBCHDigit(f.G15)>=0;)b^=f.G15<<f.getBCHDigit(b)-f.getBCHDigit(f.G15);return(a<<10|b)^f.G15_MASK},getBCHTypeNumber:function(a){for(var b=a<<12;f.getBCHDigit(b)-f.getBCHDigit(f.G18)>=0;)b^=f.G18<<f.getBCHDigit(b)-f.getBCHDigit(f.G18);return a<<12|b},getBCHDigit:function(a){for(var b=0;0!=a;)b++,a>>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<<h;for(var h=8;256>h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;c<this.getLength();c++)for(var d=0;d<a.getLength();d++)b[c+d]^=g.gexp(g.glog(this.get(c))+g.glog(a.get(d)));return new i(b,0)},mod:function(a){if(this.getLength()-a.getLength()<0)return this;for(var b=g.glog(this.get(0))-g.glog(a.get(0)),c=new Array(this.getLength()),d=0;d<this.getLength();d++)c[d]=this.get(d);for(var d=0;d<a.getLength();d++)c[d]^=g.gexp(g.glog(a.get(d))+b);return new i(c,0).mod(a)}},j.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]],j.getRSBlocks=function(a,b){var c=j.getRsBlockTable(a,b);if(void 0==c)throw new Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+b);for(var d=c.length/3,e=[],f=0;d>f;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=['<table style="border:0;border-collapse:collapse;">'],h=0;d>h;h++){g.push("<tr>");for(var i=0;d>i;i++)g.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:'+e+"px;height:"+f+"px;background-color:"+(a.isDark(h,i)?b.colorDark:b.colorLight)+';"></td>');g.push("</tr>")}g.push("</table>"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); | |
| 0 | 2 | \ No newline at end of file | ... | ... |