优化完善支付应用和支付渠道代码逻辑,完善单元测试,基于validator完成手动校验config
This commit is contained in:
parent
b18cd457c8
commit
6069a387ea
|
@ -22,3 +22,19 @@ INSERT INTO `sys_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `cre
|
|||
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 'v2', 'v2', 'pay_channel_wechat_version', 0, 'v2版本', '1', '2021-11-08 17:00:58', '1', '2021-11-08 17:00:58', b'0');
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'v3', 'v3', 'pay_channel_wechat_version', 0, 'v3版本', '1', '2021-11-08 17:01:07', '1', '2021-11-08 17:01:07', b'0');
|
||||
|
||||
-- 支付渠道支付宝算法类型
|
||||
INSERT INTO `sys_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ('支付渠道支付宝算法类型', 'pay_channel_alipay_sign_type', 0, '支付渠道支付宝算法类型', '1', '2021-11-18 15:39:09', '1', '2021-11-18 15:39:09', b'0');
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 'RSA2', 'RSA2', 'pay_channel_alipay_sign_type', 0, 'RSA2', '1', '2021-11-18 15:39:29', '1', '2021-11-18 15:39:29', b'0');
|
||||
|
||||
|
||||
-- 支付渠道支付宝公钥类型
|
||||
INSERT INTO `sys_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ('支付渠道支付宝公钥类型', 'pay_channel_alipay_mode', 0, '支付渠道支付宝公钥类型', '1', '2021-11-18 15:44:28', '1', '2021-11-18 15:44:28', b'0');
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '公钥模式', '1', 'pay_channel_alipay_mode', 0, '公钥模式:privateKey + alipayPublicKey', '1', '2021-11-18 15:45:23', '1', '2021-11-18 15:45:23', b'0');
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '证书模式', '2', 'pay_channel_alipay_mode', 0, '证书模式:appCertContent + alipayPublicCertContent + rootCertContent', '1', '2021-11-18 15:45:40', '1', '2021-11-18 15:45:40', b'0');
|
||||
|
||||
|
||||
-- 支付宝网关地址
|
||||
INSERT INTO `sys_dict_type` (`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES ('支付宝网关地址', 'pay_channel_alipay_server_type', 0, '支付宝网关地址', '1', '2021-11-18 16:58:55', '1', '2021-11-18 17:01:34', b'0');
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '线上', 'https://openapi.alipay.com/gateway.do', 'pay_channel_alipay_server_type', 0, '网关地址 - 线上', '1', '2021-11-18 16:59:32', '1', '2021-11-21 17:37:29', b'0');
|
||||
INSERT INTO `sys_dict_data` (`sort`, `label`, `value`, `dict_type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '沙箱', 'https://openapi.alipaydev.com/gateway.do', 'pay_channel_alipay_server_type', 0, '网关地址 - 沙箱', '1', '2021-11-18 16:59:48', '1', '2021-11-21 17:37:39', b'0');
|
||||
|
|
|
@ -123,7 +123,7 @@ public class PayAppController {
|
|||
|
||||
// 得到所有的应用编号,查出所有的通道
|
||||
Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId);
|
||||
List<PayChannelDO> channels = channelService.getSimpleChannels(payAppIds);
|
||||
List<PayChannelDO> channels = channelService.getChannelListByAppIds(payAppIds);
|
||||
|
||||
// 得到所有的商户信息
|
||||
Collection<Long> merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId);
|
||||
|
|
|
@ -27,8 +27,8 @@ public class PayAppExportReqVO {
|
|||
@ApiModelProperty(value = "退款结果的回调地址")
|
||||
private String refundNotifyUrl;
|
||||
|
||||
@ApiModelProperty(value = "商户编号")
|
||||
private Long merchantId;
|
||||
@ApiModelProperty(value = "商户名称")
|
||||
private String merchantName;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
|
|
|
@ -1,40 +1,35 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
/**
|
||||
* 支付渠道 controller 组件
|
||||
* @author aquan
|
||||
*/
|
||||
@Api(tags = "支付渠道")
|
||||
@RestController
|
||||
@RequestMapping("/pay/channel")
|
||||
|
@ -44,7 +39,7 @@ public class PayChannelController {
|
|||
@Resource
|
||||
private PayChannelService channelService;
|
||||
|
||||
// todo 芋艿 这几个生成的方法是没用到的 您看要不删除了把? -----start
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:create')")
|
||||
|
@ -108,28 +103,7 @@ public class PayChannelController {
|
|||
ExcelUtils.write(response, "支付渠道.xls", "数据", PayChannelExcelVO.class, datas);
|
||||
}
|
||||
|
||||
// todo 芋艿 这几个生成的方法是没用到的 您看要不删除了把? -----end
|
||||
|
||||
@PostMapping("/parsing-pem")
|
||||
@ApiOperation("解析pem证书转换为字符串")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:parsing')")
|
||||
@ApiImplicitParam(name = "file", value = "pem文件", required = true, dataTypeClass = MultipartFile.class)
|
||||
public CommonResult<String> parsingPemFile(@RequestParam("file") MultipartFile file) {
|
||||
return success(channelService.parsingPemFile(file));
|
||||
}
|
||||
|
||||
@PostMapping("/create-wechat")
|
||||
@ApiOperation("创建支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:create')")
|
||||
public CommonResult<Long> createWechatChannel(@Valid @RequestBody PayWechatChannelCreateReqVO reqVO) {
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
this.paramAdvanceCheck(reqVO.getWeChatConfig().getApiVersion(),reqVO.getWeChatConfig().getMchKey(),
|
||||
reqVO.getWeChatConfig().getPrivateKeyContent(),reqVO.getWeChatConfig().getPrivateCertContent());
|
||||
|
||||
return success(channelService.createWechatChannel(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/get-wechat")
|
||||
@GetMapping("/get-channel")
|
||||
@ApiOperation("根据条件查询微信支付渠道")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "merchantId", value = "商户编号",
|
||||
|
@ -140,51 +114,16 @@ public class PayChannelController {
|
|||
required = true, example = "wx_pub", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:query')")
|
||||
public CommonResult<PayWeChatChannelRespVO> getWeChatChannel(
|
||||
public CommonResult<PayChannelRespVO> getChannel(
|
||||
@RequestParam Long merchantId, @RequestParam Long appId, @RequestParam String code) {
|
||||
|
||||
// 獲取渠道
|
||||
PayChannelDO channel = channelService.getChannelByConditions(merchantId, appId, code);
|
||||
if (channel == null) {
|
||||
return success(new PayWeChatChannelRespVO());
|
||||
return success(new PayChannelRespVO());
|
||||
}
|
||||
|
||||
// 拼凑数据
|
||||
PayWeChatChannelRespVO respVo = PayChannelConvert.INSTANCE.convert2(channel);
|
||||
WXPayClientConfig config = (WXPayClientConfig) channel.getConfig();
|
||||
respVo.setWeChatConfig(PayChannelConvert.INSTANCE.configConvert(config));
|
||||
PayChannelRespVO respVo = PayChannelConvert.INSTANCE.convert(channel);
|
||||
return success(respVo);
|
||||
}
|
||||
|
||||
@PutMapping("/update-wechat")
|
||||
@ApiOperation("更新微信支付渠道 ")
|
||||
@PreAuthorize("@ss.hasPermission('pay:channel:update')")
|
||||
public CommonResult<Boolean> updateWechatChannel(@Valid @RequestBody PayWechatChannelUpdateReqVO updateReqVO) {
|
||||
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
this.paramAdvanceCheck(updateReqVO.getWeChatConfig().getApiVersion(),updateReqVO.getWeChatConfig().getMchKey(),
|
||||
updateReqVO.getWeChatConfig().getPrivateKeyContent(),updateReqVO.getWeChatConfig().getPrivateCertContent());
|
||||
|
||||
channelService.updateWechatChannel(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预检测微信秘钥参数
|
||||
* @param version 版本
|
||||
* @param mchKey v2版本秘钥
|
||||
* @param privateKeyContent v3版本apiclient_key
|
||||
* @param privateCertContent v3版本中apiclient_cert
|
||||
*/
|
||||
private void paramAdvanceCheck(String version, String mchKey, String privateKeyContent, String privateCertContent) {
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
if (version.equals(WXPayClientConfig.API_VERSION_V2)) {
|
||||
Assert.notNull(mchKey, "v2版本中商户密钥不可为空");
|
||||
}
|
||||
if (version.equals(WXPayClientConfig.API_VERSION_V3)) {
|
||||
Assert.notNull(privateKeyContent, "v3版本apiclient_key.pem不可为空");
|
||||
Assert.notNull(privateCertContent, "v3版本中apiclient_cert.pem不可为空");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@ApiModel("支付渠道 创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class PayChannelCreateReqVO extends PayChannelBaseVO {
|
||||
|
||||
// TODO @aquan:我在想,要不这个创建和修改特殊一点。前端传递 string 过来,后端解析成对应的。因为有 code,所以我们都知道是哪个配置类。
|
||||
// 然后,在 PayChannelEnum 里,枚举每个渠道对应的配置类。另外,我们就不单独给配置类搞 vo 了。参数校验,通过手动调用 Validator 去校验。
|
||||
// 通过这样的方式,VO 和 api 都收成,一个 update,一个 create
|
||||
|
||||
@ApiModelProperty(value = "通道配置的json字符串")
|
||||
@NotBlank(message = "通道配置不能为空")
|
||||
private String config;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -16,4 +16,6 @@ public class PayChannelRespVO extends PayChannelBaseVO {
|
|||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
@ApiModelProperty(value = "配置", required = true)
|
||||
private String config;
|
||||
}
|
||||
|
|
|
@ -15,4 +15,7 @@ public class PayChannelUpdateReqVO extends PayChannelBaseVO {
|
|||
@NotNull(message = "商户编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "通道配置的json字符串")
|
||||
@NotBlank(message = "通道配置不能为空")
|
||||
private String config;
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("支付微信渠道 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class PayWeChatChannelRespVO extends PayChannelBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "商户编号", required = true)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 微信配置类
|
||||
*/
|
||||
@Valid
|
||||
private WeChatConfig weChatConfig;
|
||||
|
||||
/**
|
||||
* 微信配置类
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("微信配置类")
|
||||
public static class WeChatConfig {
|
||||
|
||||
@ApiModelProperty(value = "公众号或者小程序的 appid", required = true, example = "wx041349c6f39b261b")
|
||||
private String appId;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "商户号", required = true, example = "1545083881")
|
||||
private String mchId;
|
||||
|
||||
@ApiModelProperty(value = "API 版本", required = true, example = "v2")
|
||||
private String apiVersion;
|
||||
|
||||
// ========== V2 版本的参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "商户密钥", required = true, example = "0alL64UDQdaCwiKZ73ib7ypaIjMns06p")
|
||||
private String mchKey;
|
||||
|
||||
/// todo @aquan 暂不支持 .p12上传 后期优化
|
||||
/// apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 对应的字符串
|
||||
/// private String keyContent;
|
||||
|
||||
// ========== V3 版本的参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "apiclient_key.pem 证书对应的字符串", required = true, example = "-----BEGIN PRIVATE KEY-----")
|
||||
private String privateKeyContent;
|
||||
|
||||
@ApiModelProperty(value = "apiclient_cert.pem 证书对应的字符串", required = true, example = "-----BEGIN CERTIFICATE-----")
|
||||
private String privateCertContent;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonClassDescription;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 支付渠道微信创建Request VO
|
||||
* @author aquan
|
||||
*/
|
||||
@ApiModel("支付渠道微信创建Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class PayWechatChannelCreateReqVO extends PayChannelBaseVO {
|
||||
|
||||
/**
|
||||
* 微信配置类
|
||||
*/
|
||||
@Valid
|
||||
private WeChatConfig weChatConfig;
|
||||
|
||||
/**
|
||||
* 微信配置类
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("微信配置类")
|
||||
public static class WeChatConfig {
|
||||
|
||||
@NotBlank(message = "公众号或者小程序的 appid不能为空")
|
||||
@ApiModelProperty(value = "公众号或者小程序的 appid", required = true, example = "wx041349c6f39b261b")
|
||||
private String appId;
|
||||
|
||||
|
||||
@NotBlank(message = "商户号不能为空")
|
||||
@ApiModelProperty(value = "商户号", required = true, example = "1545083881")
|
||||
private String mchId;
|
||||
|
||||
@NotNull(message = "API 版本不能为空")
|
||||
@ApiModelProperty(value = "API 版本", required = true, example = "v2")
|
||||
private String apiVersion;
|
||||
|
||||
// ========== V2 版本的参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "商户密钥", required = true, example = "0alL64UDQdaCwiKZ73ib7ypaIjMns06p")
|
||||
private String mchKey;
|
||||
|
||||
/// todo @aquan 暂不支持 .p12上传 后期优化
|
||||
/// apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 对应的字符串
|
||||
/// private String keyContent;
|
||||
|
||||
// ========== V3 版本的参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "apiclient_key.pem 证书对应的字符串", required = true, example = "-----BEGIN PRIVATE KEY-----")
|
||||
private String privateKeyContent;
|
||||
|
||||
@ApiModelProperty(value = "apiclient_cert.pem 证书对应的字符串", required = true, example = "-----BEGIN CERTIFICATE-----")
|
||||
private String privateCertContent;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("支付渠道 更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class PayWechatChannelUpdateReqVO extends PayChannelBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "商户编号", required = true)
|
||||
@NotNull(message = "商户编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 微信配置类
|
||||
*/
|
||||
@Valid
|
||||
private PayWechatChannelCreateReqVO.WeChatConfig weChatConfig;
|
||||
|
||||
/**
|
||||
* 微信配置类
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("微信配置类")
|
||||
public static class WeChatConfig {
|
||||
|
||||
@NotBlank(message = "公众号或者小程序的 appid不能为空")
|
||||
@ApiModelProperty(value = "公众号或者小程序的 appid", required = true, example = "wx041349c6f39b261b")
|
||||
private String appId;
|
||||
|
||||
|
||||
@NotBlank(message = "商户号不能为空")
|
||||
@ApiModelProperty(value = "商户号", required = true, example = "1545083881")
|
||||
private String mchId;
|
||||
|
||||
@NotNull(message = "API 版本不能为空")
|
||||
@ApiModelProperty(value = "API 版本", required = true, example = "v2")
|
||||
private String apiVersion;
|
||||
|
||||
// ========== V2 版本的参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "商户密钥", required = true, example = "0alL64UDQdaCwiKZ73ib7ypaIjMns06p")
|
||||
private String mchKey;
|
||||
|
||||
/// todo @aquan 暂不支持 .p12上传 后期优化
|
||||
/// apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 对应的字符串
|
||||
/// private String keyContent;
|
||||
|
||||
// ========== V3 版本的参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "apiclient_key.pem 证书对应的字符串", required = true, example = "-----BEGIN PRIVATE KEY-----")
|
||||
private String privateKeyContent;
|
||||
|
||||
@ApiModelProperty(value = "apiclient_cert.pem 证书对应的字符串", required = true, example = "-----BEGIN CERTIFICATE-----")
|
||||
private String privateCertContent;
|
||||
|
||||
// TODO @aquan:参数校验。可以使用 @AssertTrue,v2 和 v3 的
|
||||
}
|
||||
}
|
|
@ -23,15 +23,12 @@ public interface PayChannelConvert {
|
|||
PayChannelConvert INSTANCE = Mappers.getMapper(PayChannelConvert.class);
|
||||
|
||||
@Mapping(target = "config",ignore = true)
|
||||
PayChannelDO convert(PayWechatChannelCreateReqVO bean);
|
||||
|
||||
@Mapping(target = "config",ignore = true)
|
||||
PayChannelDO convert(PayWechatChannelUpdateReqVO bean);
|
||||
|
||||
PayChannelDO convert(PayChannelCreateReqVO bean);
|
||||
|
||||
@Mapping(target = "config",ignore = true)
|
||||
PayChannelDO convert(PayChannelUpdateReqVO bean);
|
||||
|
||||
@Mapping(target = "config",expression = "java(cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString(bean.getConfig()))")
|
||||
PayChannelRespVO convert(PayChannelDO bean);
|
||||
|
||||
List<PayChannelRespVO> convertList(List<PayChannelDO> list);
|
||||
|
@ -39,13 +36,7 @@ public interface PayChannelConvert {
|
|||
PageResult<PayChannelRespVO> convertPage(PageResult<PayChannelDO> page);
|
||||
|
||||
List<PayChannelExcelVO> convertList02(List<PayChannelDO> list);
|
||||
|
||||
WXPayClientConfig configConvert(PayWechatChannelCreateReqVO.WeChatConfig bean);
|
||||
|
||||
WXPayClientConfig configConvert(PayWechatChannelUpdateReqVO.WeChatConfig bean);
|
||||
|
||||
@Mapping(target = "weChatConfig",ignore = true)
|
||||
PayWeChatChannelRespVO convert2(PayChannelDO bean);
|
||||
|
||||
PayWeChatChannelRespVO.WeChatConfig configConvert(WXPayClientConfig bean);
|
||||
}
|
||||
|
|
|
@ -31,14 +31,14 @@ public interface PayAppMapper extends BaseMapperX<PayAppDO> {
|
|||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
default List<PayAppDO> selectList(PayAppExportReqVO reqVO) {
|
||||
default List<PayAppDO> selectList(PayAppExportReqVO reqVO, Collection<Long> merchantIds) {
|
||||
return selectList(new QueryWrapperX<PayAppDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.eqIfPresent("remark", reqVO.getRemark())
|
||||
.eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
|
||||
.eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
|
||||
.eqIfPresent("merchant_id", reqVO.getMerchantId())
|
||||
.inIfPresent("merchant_id", merchantIds)
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChann
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
|
||||
|
@ -26,7 +27,7 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
|
|||
.eqIfPresent("fee_rate", reqVO.getFeeRate())
|
||||
.eqIfPresent("merchant_id", reqVO.getMerchantId())
|
||||
.eqIfPresent("app_id", reqVO.getAppId())
|
||||
.eqIfPresent("config", reqVO.getConfig())
|
||||
// .eqIfPresent("config", reqVO.getConfig())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id") );
|
||||
}
|
||||
|
@ -39,9 +40,52 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
|
|||
.eqIfPresent("fee_rate", reqVO.getFeeRate())
|
||||
.eqIfPresent("merchant_id", reqVO.getMerchantId())
|
||||
.eqIfPresent("app_id", reqVO.getAppId())
|
||||
.eqIfPresent("config", reqVO.getConfig())
|
||||
// .eqIfPresent("config", reqVO.getConfig())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id") );
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件获取通道数量
|
||||
*
|
||||
* @param merchantId 商户编号
|
||||
* @param appid 应用编号
|
||||
* @param code 通道编码
|
||||
* @return 数量
|
||||
*/
|
||||
default Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
|
||||
|
||||
return this.selectCount(new QueryWrapper<PayChannelDO>().lambda()
|
||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||
.eq(PayChannelDO::getAppId, appid)
|
||||
.eq(PayChannelDO::getCode, code)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件获取通道
|
||||
*
|
||||
* @param merchantId 商户编号
|
||||
* @param appid 应用编号
|
||||
* @param code 通道编码
|
||||
* @return 数量
|
||||
*/
|
||||
default PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) {
|
||||
return this.selectOne((new QueryWrapper<PayChannelDO>().lambda()
|
||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||
.eq(PayChannelDO::getAppId, appid)
|
||||
.eq(PayChannelDO::getCode, code)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付应用ID集合获得支付渠道列表
|
||||
*
|
||||
* @param appIds 应用编号集合
|
||||
* @return 支付渠道列表
|
||||
*/
|
||||
default List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds){
|
||||
return this.selectList(new QueryWrapper<PayChannelDO>().lambda()
|
||||
.in(PayChannelDO::getAppId, appIds));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerch
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*;
|
||||
|
||||
|
@ -39,4 +40,14 @@ public interface PayMerchantMapper extends BaseMapperX<PayMerchantDO> {
|
|||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商户名称模糊查询商户集合
|
||||
*
|
||||
* @param merchantName 商户名称
|
||||
* @return 商户集合
|
||||
*/
|
||||
default List<PayMerchantDO> getMerchantListByName(String merchantName) {
|
||||
return this.selectList(new QueryWrapper<PayMerchantDO>()
|
||||
.lambda().likeRight(PayMerchantDO::getName, merchantName));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.app.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO;
|
||||
|
@ -7,6 +8,7 @@ import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqV
|
|||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
|
@ -18,10 +20,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.APP_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
@ -43,7 +42,7 @@ public class PayAppServiceImpl implements PayAppService {
|
|||
* 商户 service 组件
|
||||
*/
|
||||
@Resource
|
||||
private PayMerchantService merchantService;
|
||||
private PayMerchantMapper merchantMapper;
|
||||
|
||||
@Override
|
||||
public Long createApp(PayAppCreateReqVO createReqVO) {
|
||||
|
@ -89,13 +88,20 @@ public class PayAppServiceImpl implements PayAppService {
|
|||
|
||||
@Override
|
||||
public PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO) {
|
||||
// TODO @aquan:会有一个场景,merchantName 匹配不到商户编号的时候,应该返回没数据的
|
||||
return appMapper.selectPage(pageReqVO, this.getMerchantCondition(pageReqVO.getMerchantName()));
|
||||
Set<Long> merchantIdList = this.getMerchantCondition(pageReqVO.getMerchantName());
|
||||
if (StrUtil.isNotBlank(pageReqVO.getMerchantName()) && CollectionUtil.isEmpty(merchantIdList)) {
|
||||
return new PageResult<>();
|
||||
}
|
||||
return appMapper.selectPage(pageReqVO, merchantIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayAppDO> getAppList(PayAppExportReqVO exportReqVO) {
|
||||
return appMapper.selectList(exportReqVO);
|
||||
Set<Long> merchantIdList = this.getMerchantCondition(exportReqVO.getMerchantName());
|
||||
if (StrUtil.isNotBlank(exportReqVO.getMerchantName()) && CollectionUtil.isEmpty(merchantIdList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return appMapper.selectList(exportReqVO, merchantIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,7 +114,7 @@ public class PayAppServiceImpl implements PayAppService {
|
|||
if (StrUtil.isBlank(merchantName)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return convertSet(merchantService.getMerchantListByName(merchantName), PayMerchantDO::getId);
|
||||
return convertSet(merchantMapper.getMerchantListByName(merchantName), PayMerchantDO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,6 +137,7 @@ public class PayAppServiceImpl implements PayAppService {
|
|||
|
||||
/**
|
||||
* 检查商户是否存在
|
||||
*
|
||||
* @param id 商户编号
|
||||
*/
|
||||
@VisibleForTesting
|
||||
|
|
|
@ -12,7 +12,7 @@ import java.util.List;
|
|||
/**
|
||||
* 支付渠道 Service 接口
|
||||
*
|
||||
* @author 芋艿 // TODO @aquan:作者不要我
|
||||
* @author aquan
|
||||
*/
|
||||
public interface PayChannelService {
|
||||
|
||||
|
@ -76,31 +76,12 @@ public interface PayChannelService {
|
|||
List<PayChannelDO> getChannelList(PayChannelExportReqVO exportReqVO);
|
||||
|
||||
/**
|
||||
* 根据支付应用ID集合获取所有的支付渠道
|
||||
* 根据支付应用ID集合获得支付渠道列表
|
||||
*
|
||||
* @param payIds 支付应用编号集合
|
||||
* @return 支付渠道
|
||||
* @param appIds 应用编号集合
|
||||
* @return 支付渠道列表
|
||||
*/
|
||||
// TODO @aquan:暂时不用提供这种哈。之前提供的原因,是数据字典比较特殊。
|
||||
List<PayChannelDO> getSimpleChannels(Collection<Long> payIds);
|
||||
|
||||
/**
|
||||
* 解析pem文件获取公钥私钥字符串
|
||||
*
|
||||
* @param file pem公私钥文件
|
||||
* @return 解析后的字符串
|
||||
*/
|
||||
// TODO @aquan:可以前端读取么?
|
||||
String parsingPemFile(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 创建微信的渠道配置
|
||||
*
|
||||
* @param reqVO 创建信息
|
||||
* @return 创建结果
|
||||
*/
|
||||
// TODO @aquan:pojo 如果要做参数校验,需要添加 @Valid
|
||||
Long createWechatChannel(PayWechatChannelCreateReqVO reqVO);
|
||||
List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds);
|
||||
|
||||
/**
|
||||
* 根据条件获取通道数量
|
||||
|
@ -122,10 +103,5 @@ public interface PayChannelService {
|
|||
*/
|
||||
PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code);
|
||||
|
||||
/**
|
||||
* 更新微信支付渠道
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateWechatChannel(PayWechatChannelUpdateReqVO updateReqVO);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,23 +1,35 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
@ -25,7 +37,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
|||
/**
|
||||
* 支付渠道 Service 实现类
|
||||
*
|
||||
* @author 芋艿 // TODO aquan:作者写自己哈
|
||||
* @author aquan
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
|
@ -36,11 +48,18 @@ public class PayChannelServiceImpl implements PayChannelService {
|
|||
private PayChannelMapper channelMapper;
|
||||
|
||||
@Override
|
||||
public Long createChannel(PayChannelCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(createReqVO);
|
||||
public Long createChannel(PayChannelCreateReqVO reqVO) {
|
||||
|
||||
// 判断是否有重复的有责无法新增
|
||||
Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
|
||||
if (channelCount > 0) {
|
||||
throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR);
|
||||
}
|
||||
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
|
||||
settingConfigAndCheckParam(channel, reqVO.getConfig());
|
||||
|
||||
channelMapper.insert(channel);
|
||||
// 返回
|
||||
return channel.getId();
|
||||
}
|
||||
|
||||
|
@ -49,8 +68,9 @@ public class PayChannelServiceImpl implements PayChannelService {
|
|||
// 校验存在
|
||||
this.validateChannelExists(updateReqVO.getId());
|
||||
// 更新
|
||||
PayChannelDO updateObj = PayChannelConvert.INSTANCE.convert(updateReqVO);
|
||||
channelMapper.updateById(updateObj);
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO);
|
||||
settingConfigAndCheckParam(channel, updateReqVO.getConfig());
|
||||
channelMapper.updateById(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,53 +108,16 @@ public class PayChannelServiceImpl implements PayChannelService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 根据支付应用ID集合获取所有的支付渠道
|
||||
* 根据支付应用ID集合获得支付渠道列表
|
||||
*
|
||||
* @param payIds 支付应用编号集合
|
||||
* @return 支付渠道
|
||||
* @param appIds 应用编号集合
|
||||
* @return 支付渠道列表
|
||||
*/
|
||||
@Override
|
||||
public List<PayChannelDO> getSimpleChannels(Collection<Long> payIds) {
|
||||
return channelMapper.selectList(new QueryWrapper<PayChannelDO>().lambda().in(PayChannelDO::getAppId, payIds));
|
||||
public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) {
|
||||
return channelMapper.getChannelListByAppIds(appIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析pem文件获取公钥私钥字符串
|
||||
*
|
||||
* @param file pem公私钥文件
|
||||
* @return 解析后的字符串
|
||||
*/
|
||||
@Override
|
||||
public String parsingPemFile(MultipartFile file) {
|
||||
try {
|
||||
return IoUtil.readUtf8(file.getInputStream());
|
||||
} catch (IOException e) {
|
||||
log.error("[parsingPemToString]读取pem[{}]文件错误", file.getOriginalFilename());
|
||||
throw exception(CHANNEL_KEY_READ_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建微信的渠道配置
|
||||
*
|
||||
* @param reqVO 创建信息
|
||||
* @return 创建结果
|
||||
*/
|
||||
@Override
|
||||
public Long createWechatChannel(PayWechatChannelCreateReqVO reqVO) {
|
||||
|
||||
// 判断是否有重复的有责无法新增
|
||||
Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
|
||||
if (channelCount > 0) {
|
||||
throw exception(EXIST_SAME_CHANNEL_ERROR);
|
||||
}
|
||||
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
|
||||
WXPayClientConfig config = PayChannelConvert.INSTANCE.configConvert(reqVO.getWeChatConfig());
|
||||
channel.setConfig(config);
|
||||
channelMapper.insert(channel);
|
||||
return channel.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件获取通道数量
|
||||
|
@ -146,14 +129,9 @@ public class PayChannelServiceImpl implements PayChannelService {
|
|||
*/
|
||||
@Override
|
||||
public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
|
||||
return this.channelMapper.selectCount(new QueryWrapper<PayChannelDO>().lambda()
|
||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||
.eq(PayChannelDO::getAppId, appid)
|
||||
.eq(PayChannelDO::getCode, code)
|
||||
);
|
||||
return this.channelMapper.getChannelCountByConditions(merchantId, appid, code);
|
||||
}
|
||||
|
||||
// TODO @aquan:service 不出现 mybatis plus 哈
|
||||
/**
|
||||
* 根据条件获取通道
|
||||
*
|
||||
|
@ -164,25 +142,76 @@ public class PayChannelServiceImpl implements PayChannelService {
|
|||
*/
|
||||
@Override
|
||||
public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) {
|
||||
return this.channelMapper.selectOne((new QueryWrapper<PayChannelDO>().lambda()
|
||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||
.eq(PayChannelDO::getAppId, appid)
|
||||
.eq(PayChannelDO::getCode, code)
|
||||
));
|
||||
return this.channelMapper.getChannelByConditions(merchantId, appid, code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新微信支付渠道
|
||||
* 检测微信秘钥参数
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
* @param config 信秘钥参数
|
||||
*/
|
||||
@Override
|
||||
public void updateWechatChannel(PayWechatChannelUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
this.validateChannelExists(updateReqVO.getId());
|
||||
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO);
|
||||
WXPayClientConfig config = PayChannelConvert.INSTANCE.configConvert(updateReqVO.getWeChatConfig());
|
||||
channel.setConfig(config);
|
||||
this.channelMapper.updateById(channel);
|
||||
private void wechatParamCheck(WXPayClientConfig config) {
|
||||
// 针对于 V2 或者 V3 版本的参数校验
|
||||
if (WXPayClientConfig.API_VERSION_V2.equals(config.getApiVersion())) {
|
||||
Assert.notNull(config.getMchKey(), CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL.getMsg());
|
||||
}
|
||||
if (WXPayClientConfig.API_VERSION_V3.equals(config.getApiVersion())) {
|
||||
Assert.notNull(config.getPrivateKeyContent(), CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL.getMsg());
|
||||
Assert.notNull(config.getPrivateCertContent(), CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL.getMsg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 设置渠道配置以及参数校验
|
||||
*
|
||||
* @param channel 渠道
|
||||
* @param configStr 配置
|
||||
*/
|
||||
private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) {
|
||||
|
||||
// 得到这个渠道是微信的还是支付宝的
|
||||
String channelType = PayChannelEnum.verifyWechatOrAliPay(channel.getCode());
|
||||
Assert.notNull(channelType, CHANNEL_NOT_EXISTS.getMsg());
|
||||
|
||||
// 进行验证
|
||||
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
|
||||
Validator validator = validatorFactory.getValidator();
|
||||
|
||||
// 微信的验证
|
||||
if (PayChannelEnum.WECHAT.equals(channelType)) {
|
||||
|
||||
WXPayClientConfig config = JSON.parseObject(configStr, WXPayClientConfig.class);
|
||||
// 判断是V2 版本还是 V3 版本
|
||||
Class clazz = config.getApiVersion().equals(WXPayClientConfig.API_VERSION_V2)
|
||||
? WXPayClientConfig.V2.class : WXPayClientConfig.V3.class;
|
||||
// 手动调用validate进行验证
|
||||
Set<ConstraintViolation<WXPayClientConfig>> validate = validator.validate(config,clazz);
|
||||
|
||||
// 断言没有异常
|
||||
Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.joining(",")));
|
||||
|
||||
channel.setConfig(config);
|
||||
}
|
||||
|
||||
// 支付宝验证
|
||||
if (PayChannelEnum.ALIPAY.equals(channelType)) {
|
||||
|
||||
AlipayPayClientConfig config = JSON.parseObject(configStr, AlipayPayClientConfig.class);
|
||||
|
||||
// 判断是V2 版本还是 V3 版本
|
||||
Class clazz = config.getMode().equals(AlipayPayClientConfig.MODE_PUBLIC_KEY)
|
||||
? AlipayPayClientConfig.ModePublicKey.class : AlipayPayClientConfig.ModeCertificate.class;
|
||||
// 手动调用validate进行验证
|
||||
Set<ConstraintViolation<AlipayPayClientConfig>> validate = validator.validate(config,clazz);
|
||||
|
||||
// 断言没有异常
|
||||
Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.joining(",")));
|
||||
channel.setConfig(config);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,15 +100,6 @@ public interface PayMerchantService {
|
|||
*/
|
||||
List<PayMerchantDO> getMerchantListByNameLimit(String merchantName);
|
||||
|
||||
/**
|
||||
* 获得指定编号的商户列表
|
||||
*
|
||||
* @param merchantIds 商户编号数组
|
||||
* @return 商户列表
|
||||
*/
|
||||
// TODO @aquan:和 getMerchantList 重复了
|
||||
List<PayMerchantDO> getSimpleMerchants(Collection<Long> merchantIds);
|
||||
|
||||
/**
|
||||
* 获得指定编号的商户 Map
|
||||
*
|
||||
|
@ -116,11 +107,7 @@ public interface PayMerchantService {
|
|||
* @return 商户 Map
|
||||
*/
|
||||
default Map<Long, PayMerchantDO> getMerchantMap(Collection<Long> merchantIds) {
|
||||
// TODO @aquan:可以不用判空,交给 getMerchantList 解决
|
||||
if (CollUtil.isEmpty(merchantIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<PayMerchantDO> list = getSimpleMerchants(merchantIds);
|
||||
List<PayMerchantDO> list = this.getMerchantList(merchantIds);
|
||||
return CollectionUtils.convertMap(list, PayMerchantDO::getId);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,9 +113,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
|
|||
*/
|
||||
@Override
|
||||
public List<PayMerchantDO> getMerchantListByName(String merchantName) {
|
||||
// TODO @aquan:Service 层,不要出现 mybatis plus 的代码,要放到 mapper 里提供。技术与业务分离,原则上
|
||||
return this.merchantMapper.selectList(new QueryWrapper<PayMerchantDO>()
|
||||
.lambda().likeRight(PayMerchantDO::getName, merchantName));
|
||||
return this.merchantMapper.getMerchantListByName(merchantName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,16 +148,6 @@ public class PayMerchantServiceImpl implements PayMerchantService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定编号的商户列表
|
||||
*
|
||||
* @param merchantIds 商户编号数组
|
||||
* @return 商户列表
|
||||
*/
|
||||
@Override
|
||||
public List<PayMerchantDO> getSimpleMerchants(Collection<Long> merchantIds) {
|
||||
return merchantMapper.selectBatchIds(merchantIds);
|
||||
}
|
||||
|
||||
// TODO @芋艿:后续增加下合适的算法
|
||||
/**
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.app.service;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.app.impl.PayAppServiceImpl;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.APP_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link PayAppServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import(PayAppServiceImpl.class)
|
||||
public class PayAppServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private PayAppServiceImpl appService;
|
||||
|
||||
@Resource
|
||||
private PayAppMapper appMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateApp_success() {
|
||||
// 准备参数
|
||||
PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long appId = appService.createApp(reqVO);
|
||||
// 断言
|
||||
assertNotNull(appId);
|
||||
// 校验记录的属性是否正确
|
||||
PayAppDO app = appMapper.selectById(appId);
|
||||
assertPojoEquals(reqVO, app);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateApp_success() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class);
|
||||
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
|
||||
o.setId(dbApp.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
appService.updateApp(reqVO);
|
||||
// 校验是否更新正确
|
||||
PayAppDO app = appMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, app);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateApp_notExists() {
|
||||
// 准备参数
|
||||
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteApp_success() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class);
|
||||
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbApp.getId();
|
||||
|
||||
// 调用
|
||||
appService.deleteApp(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(appMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteApp_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetAppPage() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setPayNotifyUrl(null);
|
||||
o.setRefundNotifyUrl(null);
|
||||
o.setMerchantId(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
appMapper.insert(dbApp);
|
||||
// 测试 name 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName(null)));
|
||||
// 测试 status 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark(null)));
|
||||
// 测试 payNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl(null)));
|
||||
// 测试 refundNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(null)));
|
||||
// 测试 createTime 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayAppPageReqVO reqVO = new PayAppPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setPayNotifyUrl(null);
|
||||
reqVO.setRefundNotifyUrl(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbApp, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test // TODO aquan:请修改 null 为需要的值
|
||||
public void testGetAppList() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setPayNotifyUrl(null);
|
||||
o.setRefundNotifyUrl(null);
|
||||
o.setMerchantId(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
appMapper.insert(dbApp);
|
||||
// 测试 name 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName(null)));
|
||||
// 测试 status 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark(null)));
|
||||
// 测试 payNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl(null)));
|
||||
// 测试 refundNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(null)));
|
||||
// 测试 createTime 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayAppExportReqVO reqVO = new PayAppExportReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setPayNotifyUrl(null);
|
||||
reqVO.setRefundNotifyUrl(null);
|
||||
reqVO.setMerchantId(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
List<PayAppDO> list = appService.getAppList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbApp, list.get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.channel;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link PayChannelServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import(PayChannelServiceImpl.class)
|
||||
public class PayChannelServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private PayChannelServiceImpl channelService;
|
||||
|
||||
@Resource
|
||||
private PayChannelMapper channelMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateChannel_success() {
|
||||
// 准备参数
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long channelId = channelService.createChannel(reqVO);
|
||||
// 断言
|
||||
assertNotNull(channelId);
|
||||
// 校验记录的属性是否正确
|
||||
PayChannelDO channel = channelMapper.selectById(channelId);
|
||||
assertPojoEquals(reqVO, channel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_success() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class);
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
|
||||
o.setId(dbChannel.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
channelService.updateChannel(reqVO);
|
||||
// 校验是否更新正确
|
||||
PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, channel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_notExists() {
|
||||
// 准备参数
|
||||
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChannel_success() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class);
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbChannel.getId();
|
||||
|
||||
// 调用
|
||||
channelService.deleteChannel(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(channelMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChannel_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetChannelPage() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
|
||||
o.setCode(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setFeeRate(null);
|
||||
o.setMerchantId(null);
|
||||
o.setAppId(null);
|
||||
o.setConfig(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
channelMapper.insert(dbChannel);
|
||||
// 测试 code 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCode(null)));
|
||||
// 测试 status 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setRemark(null)));
|
||||
// 测试 feeRate 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setFeeRate(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setMerchantId(null)));
|
||||
// 测试 appId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setAppId(null)));
|
||||
// 测试 config 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setConfig(null)));
|
||||
// 测试 createTime 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayChannelPageReqVO reqVO = new PayChannelPageReqVO();
|
||||
reqVO.setCode(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setFeeRate(null);
|
||||
reqVO.setMerchantId(null);
|
||||
reqVO.setAppId(null);
|
||||
reqVO.setConfig(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbChannel, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test // TODO aquan:请修改 null 为需要的值
|
||||
public void testGetChannelList() {
|
||||
// mock 数据
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
|
||||
o.setCode(null);
|
||||
o.setStatus(null);
|
||||
o.setRemark(null);
|
||||
o.setFeeRate(null);
|
||||
o.setMerchantId(null);
|
||||
o.setAppId(null);
|
||||
o.setConfig(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
channelMapper.insert(dbChannel);
|
||||
// 测试 code 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCode(null)));
|
||||
// 测试 status 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setStatus(null)));
|
||||
// 测试 remark 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setRemark(null)));
|
||||
// 测试 feeRate 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setFeeRate(null)));
|
||||
// 测试 merchantId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setMerchantId(null)));
|
||||
// 测试 appId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setAppId(null)));
|
||||
// 测试 config 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setConfig(null)));
|
||||
// 测试 createTime 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
PayChannelExportReqVO reqVO = new PayChannelExportReqVO();
|
||||
reqVO.setCode(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setRemark(null);
|
||||
reqVO.setFeeRate(null);
|
||||
reqVO.setMerchantId(null);
|
||||
reqVO.setAppId(null);
|
||||
reqVO.setConfig(null);
|
||||
reqVO.setBeginCreateTime(null);
|
||||
reqVO.setEndCreateTime(null);
|
||||
|
||||
// 调用
|
||||
List<PayChannelDO> list = channelService.getChannelList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbChannel, list.get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.app;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.app.impl.PayAppServiceImpl;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link PayAppServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import(PayAppServiceImpl.class)
|
||||
public class PayAppServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private PayAppServiceImpl appService;
|
||||
|
||||
@Resource
|
||||
private PayAppMapper appMapper;
|
||||
|
||||
@MockBean(name = "payMerchantMapper")
|
||||
private PayMerchantMapper payMerchantMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateApp_success() {
|
||||
// 准备参数
|
||||
PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class, o ->
|
||||
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
|
||||
|
||||
// 调用
|
||||
Long appId = appService.createApp(reqVO);
|
||||
// 断言
|
||||
assertNotNull(appId);
|
||||
// 校验记录的属性是否正确
|
||||
PayAppDO app = appMapper.selectById(appId);
|
||||
assertPojoEquals(reqVO, app);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateApp_success() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o ->
|
||||
o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
||||
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setId(dbApp.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
appService.updateApp(reqVO);
|
||||
// 校验是否更新正确
|
||||
PayAppDO app = appMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, app);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateApp_notExists() {
|
||||
// 准备参数
|
||||
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o ->
|
||||
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteApp_success() {
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o ->
|
||||
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
|
||||
appMapper.insert(dbApp);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbApp.getId();
|
||||
|
||||
// 调用
|
||||
appService.deleteApp(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(appMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteApp_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAppPage() {
|
||||
Long merchantId = 1L;
|
||||
Long mismatchMerchantId = 2L;
|
||||
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
|
||||
o.setName("灿灿姐的杂货铺");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setRemark("敏敏姐的小卖铺");
|
||||
o.setPayNotifyUrl("https://www.hc.com");
|
||||
o.setRefundNotifyUrl("https://www.xm.com");
|
||||
o.setMerchantId(merchantId);
|
||||
o.setCreateTime(buildTime(2021,11,20));
|
||||
});
|
||||
|
||||
// mock 数据
|
||||
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到
|
||||
o.setId(merchantId);
|
||||
o.setNo("M1008611");
|
||||
o.setName("灿哥的杂货铺");
|
||||
o.setShortName("灿灿子");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setRemark("灿哥的杂货铺");
|
||||
o.setCreateTime(buildTime(2021,11,3));
|
||||
});
|
||||
|
||||
Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName()))
|
||||
.thenReturn(Collections.singletonList(dbMerchant));
|
||||
|
||||
appMapper.insert(dbApp);
|
||||
// 测试 name 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName("敏敏姐的杂货铺")));
|
||||
// 测试 status 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||
// 测试 remark 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark("灿灿姐的小卖部")));
|
||||
// 测试 payNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl("xm.com")));
|
||||
// 测试 refundNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl("hc.com")));
|
||||
// 测试 merchantId 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(mismatchMerchantId)));
|
||||
// 测试 createTime 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(buildTime(2021,12,21))));
|
||||
// 准备参数
|
||||
PayAppPageReqVO reqVO = new PayAppPageReqVO();
|
||||
reqVO.setName("灿灿姐的杂货铺");
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setRemark("敏敏姐的小卖铺");
|
||||
reqVO.setPayNotifyUrl("https://www.hc.com");
|
||||
reqVO.setRefundNotifyUrl("https://www.xm.com");
|
||||
reqVO.setMerchantName(dbMerchant.getName());
|
||||
reqVO.setBeginCreateTime(buildTime(2021,11,19));
|
||||
reqVO.setEndCreateTime(buildTime(2021,11,21));
|
||||
|
||||
// 调用
|
||||
PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbApp, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetAppList() {
|
||||
Long merchantId = 1L;
|
||||
Long mismatchMerchantId = 2L;
|
||||
|
||||
// mock 数据
|
||||
PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
|
||||
o.setName("灿灿姐的杂货铺");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setRemark("敏敏姐的小卖铺");
|
||||
o.setPayNotifyUrl("https://www.hc.com");
|
||||
o.setRefundNotifyUrl("https://www.xm.com");
|
||||
o.setMerchantId(merchantId);
|
||||
o.setCreateTime(buildTime(2021,11,20));
|
||||
});
|
||||
|
||||
// mock 数据
|
||||
PayMerchantDO dbMerchant = randomPojo(PayMerchantDO.class, o -> { // 等会查询到
|
||||
o.setId(merchantId);
|
||||
o.setNo("M1008611");
|
||||
o.setName("灿哥的杂货铺");
|
||||
o.setShortName("灿灿子");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setRemark("灿哥的杂货铺");
|
||||
o.setCreateTime(buildTime(2021,11,3));
|
||||
});
|
||||
|
||||
Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName()))
|
||||
.thenReturn(Collections.singletonList(dbMerchant));
|
||||
|
||||
appMapper.insert(dbApp);
|
||||
// 测试 name 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setName("敏敏姐的杂货铺")));
|
||||
// 测试 status 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||
// 测试 remark 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRemark("灿灿姐的小卖部")));
|
||||
// 测试 payNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setPayNotifyUrl("xm.com")));
|
||||
// 测试 refundNotifyUrl 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setRefundNotifyUrl("hc.com")));
|
||||
// 测试 merchantId 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setMerchantId(mismatchMerchantId)));
|
||||
// 测试 createTime 不匹配
|
||||
appMapper.insert(ObjectUtils.clone(dbApp, o -> o.setCreateTime(buildTime(2021,12,21))));
|
||||
// 准备参数
|
||||
PayAppExportReqVO reqVO = new PayAppExportReqVO();
|
||||
reqVO.setName("灿灿姐的杂货铺");
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setRemark("敏敏姐的小卖铺");
|
||||
reqVO.setPayNotifyUrl("https://www.hc.com");
|
||||
reqVO.setRefundNotifyUrl("https://www.xm.com");
|
||||
reqVO.setMerchantName(dbMerchant.getName());
|
||||
reqVO.setBeginCreateTime(buildTime(2021,11,19));
|
||||
reqVO.setEndCreateTime(buildTime(2021,11,21));
|
||||
|
||||
// 调用
|
||||
List<PayAppDO> list = appService.getAppList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbApp, list.get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,404 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Validator;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link PayChannelServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋艿
|
||||
*/
|
||||
@Import(PayChannelServiceImpl.class)
|
||||
public class PayChannelServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private PayChannelServiceImpl channelService;
|
||||
|
||||
@Resource
|
||||
private PayChannelMapper channelMapper;
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateWechatVersion2Channel_success() {
|
||||
// 准备参数
|
||||
|
||||
WXPayClientConfig v2Config = getV2Config();
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
|
||||
o.setCode(PayChannelEnum.WX_PUB.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(JSON.toJSONString(v2Config));
|
||||
});
|
||||
|
||||
// 调用
|
||||
Long channelId = channelService.createChannel(reqVO);
|
||||
// 断言
|
||||
assertNotNull(channelId);
|
||||
// 校验记录的属性是否正确
|
||||
PayChannelDO channel = channelMapper.selectById(channelId);
|
||||
assertPojoEquals(reqVO, channel, "config");
|
||||
// 关于config 对象应该拿出来重新对比
|
||||
assertPojoEquals(v2Config, channel.getConfig());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWechatVersion3Channel_success() {
|
||||
// 准备参数
|
||||
|
||||
WXPayClientConfig v3Config = getV3Config();
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
|
||||
o.setCode(PayChannelEnum.WX_PUB.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(JSON.toJSONString(v3Config));
|
||||
});
|
||||
|
||||
// 调用
|
||||
Long channelId = channelService.createChannel(reqVO);
|
||||
// 断言
|
||||
assertNotNull(channelId);
|
||||
// 校验记录的属性是否正确
|
||||
PayChannelDO channel = channelMapper.selectById(channelId);
|
||||
assertPojoEquals(reqVO, channel, "config");
|
||||
// 关于config 对象应该拿出来重新对比
|
||||
assertPojoEquals(v3Config, channel.getConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAliPayPublicKeyChannel_success() {
|
||||
// 准备参数
|
||||
|
||||
AlipayPayClientConfig payClientConfig = getPublicKeyConfig();
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(JSON.toJSONString(payClientConfig));
|
||||
});
|
||||
|
||||
// 调用
|
||||
Long channelId = channelService.createChannel(reqVO);
|
||||
// 断言
|
||||
assertNotNull(channelId);
|
||||
// 校验记录的属性是否正确
|
||||
PayChannelDO channel = channelMapper.selectById(channelId);
|
||||
assertPojoEquals(reqVO, channel, "config");
|
||||
// 关于config 对象应该拿出来重新对比
|
||||
assertPojoEquals(payClientConfig, channel.getConfig());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAliPayCertificateChannel_success() {
|
||||
// 准备参数
|
||||
|
||||
AlipayPayClientConfig payClientConfig = getCertificateConfig();
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(JSON.toJSONString(payClientConfig));
|
||||
});
|
||||
|
||||
// 调用
|
||||
Long channelId = channelService.createChannel(reqVO);
|
||||
// 断言
|
||||
assertNotNull(channelId);
|
||||
// 校验记录的属性是否正确
|
||||
PayChannelDO channel = channelMapper.selectById(channelId);
|
||||
assertPojoEquals(reqVO, channel, "config");
|
||||
// 关于config 对象应该拿出来重新对比
|
||||
assertPojoEquals(payClientConfig, channel.getConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_success() {
|
||||
// mock 数据
|
||||
AlipayPayClientConfig payClientConfig = getCertificateConfig();
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> {
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(payClientConfig);
|
||||
});
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
AlipayPayClientConfig payClientPublicKeyConfig = getPublicKeyConfig();
|
||||
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
|
||||
o.setCode(dbChannel.getCode());
|
||||
o.setStatus(dbChannel.getStatus());
|
||||
o.setConfig(JSON.toJSONString(payClientPublicKeyConfig));
|
||||
o.setId(dbChannel.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
channelService.updateChannel(reqVO);
|
||||
// 校验是否更新正确
|
||||
PayChannelDO channel = channelMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, channel, "config");
|
||||
assertPojoEquals(payClientPublicKeyConfig, channel.getConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannel_notExists() {
|
||||
// 准备参数
|
||||
AlipayPayClientConfig payClientPublicKeyConfig = getPublicKeyConfig();
|
||||
PayChannelUpdateReqVO reqVO = randomPojo(PayChannelUpdateReqVO.class, o -> {
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(JSON.toJSONString(payClientPublicKeyConfig));
|
||||
});
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> channelService.updateChannel(reqVO), CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChannel_success() {
|
||||
// mock 数据
|
||||
AlipayPayClientConfig payClientConfig = getCertificateConfig();
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> {
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setConfig(payClientConfig);
|
||||
});
|
||||
channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbChannel.getId();
|
||||
|
||||
// 调用
|
||||
channelService.deleteChannel(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(channelMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChannel_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> channelService.deleteChannel(id), CHANNEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test // TODO 请修改 null 为需要的值
|
||||
public void testGetChannelPage() {
|
||||
// mock 数据
|
||||
AlipayPayClientConfig payClientConfig = getCertificateConfig();
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setRemark("灿灿子的支付渠道");
|
||||
o.setFeeRate(0.03);
|
||||
o.setMerchantId(1L);
|
||||
o.setAppId(1L);
|
||||
o.setConfig(payClientConfig);
|
||||
o.setCreateTime(buildTime(2021,11,20));
|
||||
});
|
||||
channelMapper.insert(dbChannel);
|
||||
// 执行拷贝的时候会出现异常,所以在插入后要重置为null 后续在写入新的
|
||||
dbChannel.setConfig(null);
|
||||
// 测试 code 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setCode(PayChannelEnum.WX_PUB.getCode());
|
||||
}));
|
||||
// 测试 status 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
}));
|
||||
// 测试 remark 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o ->{
|
||||
o.setConfig(payClientConfig);
|
||||
o.setRemark("敏敏子的渠道");
|
||||
}));
|
||||
// 测试 feeRate 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setFeeRate(1.23);
|
||||
}));
|
||||
// 测试 merchantId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setMerchantId(2L);
|
||||
}));
|
||||
// 测试 appId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setAppId(2L);
|
||||
}));
|
||||
// 测试 createTime 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setCreateTime(buildTime(2021, 10, 20));
|
||||
}));
|
||||
// 准备参数
|
||||
PayChannelPageReqVO reqVO = new PayChannelPageReqVO();
|
||||
reqVO.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setRemark("灿灿子的支付渠道");
|
||||
reqVO.setFeeRate(0.03);
|
||||
reqVO.setMerchantId(1L);
|
||||
reqVO.setAppId(1L);
|
||||
reqVO.setConfig(JSON.toJSONString(payClientConfig));
|
||||
reqVO.setBeginCreateTime(buildTime(2021,11,19));
|
||||
reqVO.setEndCreateTime(buildTime(2021,11,21));
|
||||
|
||||
// 调用
|
||||
PageResult<PayChannelDO> pageResult = channelService.getChannelPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbChannel, pageResult.getList().get(0), "config");
|
||||
assertPojoEquals(payClientConfig, pageResult.getList().get(0).getConfig());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetChannelList() {
|
||||
// mock 数据
|
||||
AlipayPayClientConfig payClientConfig = getCertificateConfig();
|
||||
PayChannelDO dbChannel = randomPojo(PayChannelDO.class, o -> { // 等会查询到
|
||||
o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setRemark("灿灿子的支付渠道");
|
||||
o.setFeeRate(0.03);
|
||||
o.setMerchantId(1L);
|
||||
o.setAppId(1L);
|
||||
o.setConfig(payClientConfig);
|
||||
o.setCreateTime(buildTime(2021,11,20));
|
||||
});
|
||||
channelMapper.insert(dbChannel);
|
||||
// 执行拷贝的时候会出现异常,所以在插入后要重置为null 后续在写入新的
|
||||
dbChannel.setConfig(null);
|
||||
// 测试 code 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setCode(PayChannelEnum.WX_PUB.getCode());
|
||||
}));
|
||||
// 测试 status 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
}));
|
||||
// 测试 remark 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o ->{
|
||||
o.setConfig(payClientConfig);
|
||||
o.setRemark("敏敏子的渠道");
|
||||
}));
|
||||
// 测试 feeRate 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setFeeRate(1.23);
|
||||
}));
|
||||
// 测试 merchantId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setMerchantId(2L);
|
||||
}));
|
||||
// 测试 appId 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setAppId(2L);
|
||||
}));
|
||||
// 测试 createTime 不匹配
|
||||
channelMapper.insert(ObjectUtils.clone(dbChannel, o -> {
|
||||
o.setConfig(payClientConfig);
|
||||
o.setCreateTime(buildTime(2021, 10, 20));
|
||||
}));
|
||||
// 准备参数
|
||||
PayChannelExportReqVO reqVO = new PayChannelExportReqVO();
|
||||
reqVO.setCode(PayChannelEnum.ALIPAY_APP.getCode());
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setRemark("灿灿子的支付渠道");
|
||||
reqVO.setFeeRate(0.03);
|
||||
reqVO.setMerchantId(1L);
|
||||
reqVO.setAppId(1L);
|
||||
reqVO.setConfig(JSON.toJSONString(payClientConfig));
|
||||
reqVO.setBeginCreateTime(buildTime(2021,11,19));
|
||||
reqVO.setEndCreateTime(buildTime(2021,11,21));
|
||||
|
||||
// 调用
|
||||
List<PayChannelDO> list = channelService.getChannelList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbChannel, list.get(0), "config");
|
||||
assertPojoEquals(payClientConfig, list.get(0).getConfig());
|
||||
}
|
||||
|
||||
|
||||
public WXPayClientConfig getV2Config() {
|
||||
return new WXPayClientConfig()
|
||||
.setAppId("APP00001")
|
||||
.setMchId("MCH00001")
|
||||
.setApiVersion(WXPayClientConfig.API_VERSION_V2)
|
||||
.setMchKey("dsa1d5s6a1d6sa16d1sa56d15a61das6")
|
||||
.setApiV3Key("")
|
||||
.setPrivateCertContent("")
|
||||
.setPrivateKeyContent("");
|
||||
}
|
||||
|
||||
public WXPayClientConfig getV3Config() {
|
||||
return new WXPayClientConfig()
|
||||
.setAppId("APP00001")
|
||||
.setMchId("MCH00001")
|
||||
.setApiVersion(WXPayClientConfig.API_VERSION_V3)
|
||||
.setMchKey("")
|
||||
.setApiV3Key("sdadasdsadadsa")
|
||||
.setPrivateKeyContent("dsa445das415d15asd16ad156as")
|
||||
.setPrivateCertContent("dsadasd45asd4s5a");
|
||||
|
||||
}
|
||||
|
||||
public AlipayPayClientConfig getPublicKeyConfig() {
|
||||
return new AlipayPayClientConfig()
|
||||
.setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD)
|
||||
.setAppId("APP00001")
|
||||
.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
|
||||
.setMode(AlipayPayClientConfig.MODE_PUBLIC_KEY)
|
||||
.setPrivateKey("13131321312")
|
||||
.setAlipayPublicKey("13321321321")
|
||||
.setAppCertContent("")
|
||||
.setAlipayPublicCertContent("")
|
||||
.setRootCertContent("");
|
||||
}
|
||||
|
||||
public AlipayPayClientConfig getCertificateConfig() {
|
||||
return new AlipayPayClientConfig()
|
||||
.setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD)
|
||||
.setAppId("APP00001")
|
||||
.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
|
||||
.setMode(AlipayPayClientConfig.MODE_CERTIFICATE)
|
||||
.setPrivateKey("")
|
||||
.setAlipayPublicKey("")
|
||||
.setAppCertContent("13321321321sda")
|
||||
.setAlipayPublicCertContent("13321321321aqeqw")
|
||||
.setRootCertContent("13321321321dsad");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package cn.iocoder.yudao.adminserver.modules.pay.merchant.service;
|
||||
package cn.iocoder.yudao.adminserver.modules.pay.service.merchant;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO;
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO;
|
||||
|
@ -54,8 +51,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest {
|
|||
assertNotNull(merchantId);
|
||||
// 校验记录的属性是否正确
|
||||
PayMerchantDO merchant = merchantMapper.selectById(merchantId);
|
||||
// TODO @aquan:需要判断 no 非空
|
||||
assertPojoEquals(reqVO, merchant,"no");
|
||||
assertPojoEquals(reqVO, merchant);
|
||||
}
|
||||
|
||||
@Test
|
|
@ -27,3 +27,5 @@ DELETE FROM "sys_social_user";
|
|||
|
||||
-- pay 开头的 DB
|
||||
DELETE FROM pay_merchant;
|
||||
DELETE FROM pay_app;
|
||||
DELETE FROM pay_channel
|
||||
|
|
|
@ -464,3 +464,37 @@ CREATE TABLE IF NOT EXISTS "pay_merchant" (
|
|||
"deleted" bit(1) NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '支付商户信息';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "pay_app" (
|
||||
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar(64) NOT NULL,
|
||||
"status" tinyint NOT NULL,
|
||||
"remark" varchar(255) DEFAULT NULL,
|
||||
`pay_notify_url` varchar(1024) NOT NULL,
|
||||
`refund_notify_url`varchar(1024) NOT NULL,
|
||||
`merchant_id`bigint(20) NOT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ,
|
||||
"updater" varchar(64) DEFAULT '',
|
||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
"deleted" bit(1) NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT = '支付应用信息';
|
||||
|
||||
CREATE TABLE "pay_channel" (
|
||||
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"code" varchar(32) NOT NULL ,
|
||||
"status" tinyint(4) NOT NULL ,
|
||||
"remark" varchar(255) DEFAULT NULL ,
|
||||
"fee_rate" double NOT NULL DEFAULT 0 ,
|
||||
"merchant_id" bigint(20) NOT NULL ,
|
||||
"app_id" bigint(20) NOT NULL ,
|
||||
"config" varchar(10240) NOT NULL ,
|
||||
"creator" varchar(64) NULL DEFAULT '' ,
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ,
|
||||
"updater" varchar(64) NULL DEFAULT '' ,
|
||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
"deleted" bit(1) NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
)COMMENT = '支付渠道';
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@ export function deleteChannel(id) {
|
|||
}
|
||||
|
||||
// 获得支付渠道
|
||||
export function getChannel(id) {
|
||||
return request({
|
||||
url: '/pay/channel/get?id=' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// export function getChannel(id) {
|
||||
// return request({
|
||||
// url: '/pay/channel/get?id=' + id,
|
||||
// method: 'get'
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
@ -56,19 +56,10 @@ export function exportChannelExcel(query) {
|
|||
})
|
||||
}
|
||||
|
||||
// 创建微信支付渠道
|
||||
export function createWechatChannel(data) {
|
||||
return request({
|
||||
url: '/pay/channel/create-wechat',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获得支付渠道
|
||||
export function getWechatChannel(merchantId,appId,code) {
|
||||
export function getChannel(merchantId,appId,code) {
|
||||
return request({
|
||||
url: '/pay/channel/get-wechat',
|
||||
url: '/pay/channel/get-channel',
|
||||
params:{
|
||||
merchantId:merchantId,
|
||||
appId:appId,
|
||||
|
@ -78,11 +69,3 @@ export function getWechatChannel(merchantId,appId,code) {
|
|||
})
|
||||
}
|
||||
|
||||
// 更新支付渠道
|
||||
export function updateWechatChannel(data) {
|
||||
return request({
|
||||
url: '/pay/channel/update-wechat',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
|
@ -121,3 +121,8 @@ export const PayChannelEnum = {
|
|||
"name": "支付宝扫码支付"
|
||||
},
|
||||
}
|
||||
|
||||
export const PayType = {
|
||||
WECHAT: "WECHAT",
|
||||
ALIPAY: "ALIPAY"
|
||||
}
|
||||
|
|
|
@ -39,7 +39,12 @@ export const DICT_TYPE = {
|
|||
PAY_CHANNEL_STATUS: 'pay_channel_status',
|
||||
// 微信渠道版本
|
||||
PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version',
|
||||
|
||||
// 支付渠道支付宝算法类型
|
||||
PAY_CHANNEL_ALIPAY_SIGN_TYPE:'pay_channel_alipay_sign_type',
|
||||
// 支付宝公钥类型
|
||||
PAY_CHANNEL_ALIPAY_MODE:'pay_channel_alipay_mode',
|
||||
// 支付宝网关地址
|
||||
PAY_CHANNEL_ALIPAY_SERVER_TYPE:'pay_channel_alipay_server_type',
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,354 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="transferParam.aliPayOpen" @closed="close" append-to-body width="800px">
|
||||
<el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px"
|
||||
v-loading="transferParam.loading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
<el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
|
||||
<template slot="append">%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="开放平台APPID" prop="aliPayConfig.appId">
|
||||
<el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="渠道状态" prop="status">
|
||||
<el-radio-group v-model="form.status" size="medium">
|
||||
<el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="网关地址" prop="aliPayConfig.serverUrl">
|
||||
<el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium">
|
||||
<el-radio v-for="dict in aliPayServerDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType">
|
||||
<el-radio-group v-model="form.aliPayConfig.signType" size="medium">
|
||||
<el-radio v-for="dict in aliPaySignTypeDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode">
|
||||
<el-radio-group v-model="form.aliPayConfig.mode" size="medium">
|
||||
<el-radio v-for="dict in aliPayModeDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="form.aliPayConfig.mode === 1">
|
||||
<el-form-item label-width="180px" label="商户私钥" prop="aliPayConfig.privateKey">
|
||||
<el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey"
|
||||
placeholder="请输入商户私钥" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="支付宝公钥字符串" prop="aliPayConfig.alipayPublicKey">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{minRows: 8, maxRows: 8}"
|
||||
v-model="form.aliPayConfig.alipayPublicKey"
|
||||
placeholder="请输入支付宝公钥字符串" clearable
|
||||
:style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="form.aliPayConfig.mode === 2">
|
||||
<el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent">
|
||||
<el-input v-model="form.aliPayConfig.appCertContent" type="textarea"
|
||||
placeholder="请上传商户公钥应用证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload
|
||||
action=""
|
||||
ref="privateKeyContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:http-request="appCertUpload"
|
||||
:before-upload="fileBeforeUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent">
|
||||
<el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea"
|
||||
placeholder="请上传支付宝公钥证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload
|
||||
ref="privateCertContentFile"
|
||||
action=""
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:before-upload="fileBeforeUpload"
|
||||
:http-request="alipayPublicCertUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent">
|
||||
<el-input
|
||||
v-model="form.aliPayConfig.rootCertContent"
|
||||
type="textarea"
|
||||
placeholder="请上传根证书"
|
||||
readonly :autosize="{minRows: 8, maxRows: 8}"
|
||||
:style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="">
|
||||
<el-upload
|
||||
ref="privateCertContentFile"
|
||||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
action=""
|
||||
:before-upload="fileBeforeUpload"
|
||||
:http-request="rootCertUpload">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label-width="180px" label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
|
||||
|
||||
const defaultForm = {
|
||||
code: '',
|
||||
status: null,
|
||||
remark: '',
|
||||
feeRate: null,
|
||||
appId: '',
|
||||
merchantId: null,
|
||||
aliPayConfig: {
|
||||
appId: '',
|
||||
serverUrl: null,
|
||||
signType: '',
|
||||
mode: null,
|
||||
privateKey: '',
|
||||
alipayPublicKey: '',
|
||||
appCertContent: '',
|
||||
alipayPublicCertContent: '',
|
||||
rootCertContent: ''
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "aliPayChannelForm",
|
||||
components: {},
|
||||
props: {
|
||||
// 传输的参数
|
||||
transferParam: {
|
||||
// 加载动画
|
||||
"loading": false,
|
||||
// 是否修改
|
||||
"edit": false,
|
||||
// 是否显示
|
||||
"aliPayOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
"payCode": null,
|
||||
// 商户对象
|
||||
"payMerchant": {
|
||||
// 编号
|
||||
"id": null,
|
||||
// 名称
|
||||
"name": null
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: JSON.parse(JSON.stringify(defaultForm)),
|
||||
rules: {
|
||||
feeRate: [{
|
||||
required: true,
|
||||
message: '请输入渠道费率',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.appId': [{
|
||||
required: true,
|
||||
message: '请输入开放平台上创建的应用的 ID',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
status: [{
|
||||
required: true,
|
||||
message: '渠道状态不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.serverUrl': [{
|
||||
required: true,
|
||||
message: '请传入网关地址',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.signType': [{
|
||||
required: true,
|
||||
message: '请传入签名算法类型',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.mode': [{
|
||||
required: true,
|
||||
message: '公钥类型不能为空',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.privateKey': [{
|
||||
required: true,
|
||||
message: '请输入商户私钥',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.alipayPublicKey': [{
|
||||
required: true,
|
||||
message: '请输入支付宝公钥字符串',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.appCertContent': [{
|
||||
required: true,
|
||||
message: '请上传商户公钥应用证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.alipayPublicCertContent': [{
|
||||
required: true,
|
||||
message: '请上传支付宝公钥证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'aliPayConfig.rootCertContent': [{
|
||||
required: true,
|
||||
message: '请上传指定根证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
},
|
||||
fileAccept: ".crt",
|
||||
// 渠道状态 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_STATUS),
|
||||
// 支付宝加密方式
|
||||
aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE),
|
||||
// 版本状态 数据字典
|
||||
aliPayModeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_MODE),
|
||||
// 支付宝网关地址
|
||||
aliPayServerDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SERVER_TYPE),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
transferParam: {
|
||||
deep: true, // 深度监听
|
||||
handler(newVal) {
|
||||
if (newVal.aliPayOpen) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
this.form.merchantId = newVal.payMerchant.id;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit === true && newVal.loading) {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
|
||||
.then(response => {
|
||||
this.form.id = response.data.id;
|
||||
this.form.feeRate = response.data.feeRate;
|
||||
this.form.status = response.data.status;
|
||||
this.form.remark = response.data.remark;
|
||||
|
||||
let config = JSON.parse(response.data.config);
|
||||
this.form.aliPayConfig.appId = config.appId;
|
||||
this.form.aliPayConfig.serverUrl = config.serverUrl;
|
||||
this.form.aliPayConfig.signType = config.signType;
|
||||
this.form.aliPayConfig.mode = config.mode;
|
||||
this.form.aliPayConfig.privateKey = config.privateKey;
|
||||
this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey;
|
||||
this.form.aliPayConfig.appCertContent = config.appCertContent;
|
||||
this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent;
|
||||
this.form.aliPayConfig.rootCertContent = config.rootCertContent;
|
||||
this.transferParam.loading = false;
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.transferParam.aliPayOpen = false;
|
||||
this.form = JSON.parse(JSON.stringify(defaultForm));
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$refs['aliPayForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
let data = this.form;
|
||||
data.config = JSON.stringify(this.form.aliPayConfig);
|
||||
if (this.transferParam.edit) {
|
||||
updateChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.close();
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
|
||||
createChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
fileBeforeUpload(file) {
|
||||
let format = '.' + file.name.split(".")[1];
|
||||
if (format !== this.fileAccept) {
|
||||
this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
|
||||
return false;
|
||||
}
|
||||
let isRightSize = file.size / 1024 / 1024 < 2
|
||||
if (!isRightSize) {
|
||||
this.$message.error('文件大小超过 2MB')
|
||||
}
|
||||
return isRightSize
|
||||
},
|
||||
appCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.aliPayConfig.appCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
alipayPublicCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.aliPayConfig.alipayPublicCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
rootCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.aliPayConfig.rootCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :visible.sync="transferParam.open" @close="close" append-to-body>
|
||||
<el-dialog :visible.sync="transferParam.wechatOpen" @close="close" append-to-body width="800px">
|
||||
<el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px"
|
||||
v-loading="transferParam.loading">
|
||||
<el-form-item label-width="180px" label="渠道费率" prop="feeRate">
|
||||
|
@ -22,7 +22,7 @@
|
|||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
|
||||
<el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
|
||||
<el-radio-group v-model="form.weChatConfig.apiVersion" size="medium">
|
||||
<el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value">
|
||||
{{ dict.label }}
|
||||
|
@ -32,9 +32,13 @@
|
|||
<el-form-item label-width="180px" label="商户秘钥" prop="weChatConfig.mchKey"
|
||||
v-if="form.weChatConfig.apiVersion === 'v2'">
|
||||
<el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户秘钥" clearable
|
||||
:style="{width: '100%'}"></el-input>
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<div v-if="form.weChatConfig.apiVersion === 'v3'">
|
||||
<el-form-item label-width="180px" label="API V3秘钥" prop="weChatConfig.apiV3Key">
|
||||
<el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入API V3秘钥" clearable
|
||||
:style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="180px" label="apiclient_key.perm证书" prop="weChatConfig.privateKeyContent">
|
||||
<el-input v-model="form.weChatConfig.privateKeyContent" type="textarea"
|
||||
placeholder="请上传apiclient_key.perm证书"
|
||||
|
@ -45,9 +49,9 @@
|
|||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:headers="header"
|
||||
:action="pemUploadAction"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:on-success="privateKeyUploadSuccess"
|
||||
:http-request="privateKeyUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
|
@ -62,9 +66,9 @@
|
|||
:limit="1"
|
||||
:accept="fileAccept"
|
||||
:headers="header"
|
||||
:action="pemUploadAction"
|
||||
action=""
|
||||
:before-upload="pemFileBeforeUpload"
|
||||
:on-success="privateCertUploadSuccess"
|
||||
:http-request="privateCertUpload"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
|
||||
</el-upload>
|
||||
|
@ -83,10 +87,28 @@
|
|||
</template>
|
||||
<script>
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {createWechatChannel, getWechatChannel, updateWechatChannel} from "@/api/pay/channel";
|
||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
|
||||
|
||||
const defaultForm = {
|
||||
code: '',
|
||||
status: null,
|
||||
remark: '',
|
||||
feeRate: null,
|
||||
appId: '',
|
||||
merchantId: null,
|
||||
weChatConfig: {
|
||||
appId: '',
|
||||
mchId: '',
|
||||
apiVersion: '',
|
||||
mchKey: '',
|
||||
privateKeyContent: '',
|
||||
privateCertContent: '',
|
||||
apiV3Key:'',
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "wechatJsApiForm",
|
||||
name: "wechatChannelForm",
|
||||
components: {},
|
||||
props: {
|
||||
// 传输的参数
|
||||
|
@ -96,7 +118,7 @@ export default {
|
|||
// 是否修改
|
||||
"edit": false,
|
||||
// 是否显示
|
||||
"open": false,
|
||||
"wechatOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
|
@ -112,22 +134,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
code: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
feeRate: undefined,
|
||||
appId: undefined,
|
||||
merchantId: undefined,
|
||||
weChatConfig: {
|
||||
appId: undefined,
|
||||
mchId: undefined,
|
||||
apiVersion: undefined,
|
||||
mchKey: undefined,
|
||||
privateKeyContent: undefined,
|
||||
privateCertContent: undefined,
|
||||
}
|
||||
},
|
||||
form: JSON.parse(JSON.stringify(defaultForm)),
|
||||
rules: {
|
||||
feeRate: [{
|
||||
required: true,
|
||||
|
@ -147,12 +154,12 @@ export default {
|
|||
status: [{
|
||||
required: true,
|
||||
message: '渠道状态不能为空',
|
||||
trigger: 'change'
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.apiVersion': [{
|
||||
required: true,
|
||||
message: 'API版本不能为空',
|
||||
trigger: 'change'
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.mchKey': [{
|
||||
required: true,
|
||||
|
@ -169,12 +176,16 @@ export default {
|
|||
message: '请上传apiclient_cert.perm证书',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
'weChatConfig.apiV3Key': [{
|
||||
required: true,
|
||||
message: '请上传apiV3秘钥值',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
},
|
||||
// 文件上传的header
|
||||
header: {
|
||||
"Authorization": null
|
||||
},
|
||||
pemUploadAction: 'http://127.0.0.1:48080/api/pay/channel/parsing-pem',
|
||||
fileAccept: ".pem",
|
||||
// 渠道状态 数据字典
|
||||
statusDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_STATUS),
|
||||
|
@ -185,51 +196,66 @@ export default {
|
|||
transferParam: {
|
||||
deep: true, // 深度监听
|
||||
handler(newVal) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
this.form.merchantId = newVal.payMerchant.id;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit === true && newVal.loading) {
|
||||
this.init();
|
||||
if (newVal.wechatOpen) {
|
||||
this.form.code = newVal.payCode;
|
||||
this.form.appId = newVal.appId;
|
||||
this.form.merchantId = newVal.payMerchant.id;
|
||||
// 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
|
||||
if (newVal.edit && newVal.loading) {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.header.Authorization = "Bearer " + this.$store.getters.token;
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
getWechatChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
|
||||
getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
|
||||
.then(response => {
|
||||
this.form = response.data;
|
||||
this.form.id = response.data.id;
|
||||
this.form.feeRate = response.data.feeRate;
|
||||
this.form.appId = response.data.appId;
|
||||
this.form.status = response.data.status;
|
||||
this.form.remark = response.data.remark;
|
||||
|
||||
let config = JSON.parse(response.data.config);
|
||||
this.form.weChatConfig.appId = config.appId;
|
||||
this.form.weChatConfig.apiVersion = config.apiVersion;
|
||||
this.form.weChatConfig.mchId = config.mchId;
|
||||
this.form.weChatConfig.mchKey = config.mchKey;
|
||||
this.form.weChatConfig.privateKeyContent = config.privateKeyContent;
|
||||
this.form.weChatConfig.privateCertContent = config.privateCertContent;
|
||||
this.form.weChatConfig.apiV3Key = config.apiV3Key;
|
||||
this.transferParam.loading = false;
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.transferParam.open = false;
|
||||
this.$refs['wechatJsApiForm'].resetFields();
|
||||
this.transferParam.wechatOpen = false;
|
||||
this.form = JSON.parse(JSON.stringify(defaultForm));
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$refs['wechatJsApiForm'].validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
let data = this.form;
|
||||
data.config = JSON.stringify(this.form.weChatConfig);
|
||||
if (this.transferParam.edit) {
|
||||
updateWechatChannel(this.form).then(response => {
|
||||
if (response.code === 0 ) {
|
||||
updateChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.close();
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
createWechatChannel(this.form).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
|
||||
createChannel(data).then(response => {
|
||||
if (response.code === 0) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.$parent.refreshTable();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -246,11 +272,19 @@ export default {
|
|||
}
|
||||
return isRightSize
|
||||
},
|
||||
privateKeyUploadSuccess(response) {
|
||||
this.form.weChatConfig.privateKeyContent = response.data;
|
||||
privateKeyUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.privateKeyContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
},
|
||||
privateCertUploadSuccess(response) {
|
||||
this.form.weChatConfig.privateCertContent = response.data;
|
||||
privateCertUpload(event) {
|
||||
const readFile = new FileReader()
|
||||
readFile.onload = (e) => {
|
||||
this.form.weChatConfig.privateCertContent = e.target.result
|
||||
}
|
||||
readFile.readAsText(event.file);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,68 +57,104 @@
|
|||
<el-table-column label="支付宝配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.DISABLE">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.DISABLE">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.DISABLE">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.ENABLE">
|
||||
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)"
|
||||
v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.DISABLE">
|
||||
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信配置" align="center">
|
||||
<el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code)"
|
||||
v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code)"
|
||||
v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)"
|
||||
v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)"
|
||||
v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.DISABLE">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code)"
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)"
|
||||
v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code)"
|
||||
v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)"
|
||||
v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.DISABLE">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="payChannelEnum.WX_APP.name" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code)"
|
||||
v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.ENABLE"></el-button>
|
||||
<el-button type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code)"
|
||||
v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.DISABLE"></el-button>
|
||||
<el-button
|
||||
type="success" icon="el-icon-check" circle
|
||||
@click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)"
|
||||
v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.ENABLE">
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger" icon="el-icon-close" circle
|
||||
@click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)"
|
||||
v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.DISABLE">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
@ -186,21 +222,24 @@
|
|||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<wechat-js-api-form :transferParam="wechatChannelParam"></wechat-js-api-form>
|
||||
<wechat-channel-form :transferParam="channelParam"></wechat-channel-form>
|
||||
<ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage, exportAppExcel} from "@/api/pay/app";
|
||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
|
||||
import {PayChannelEnum, SysCommonStatusEnum} from "@/utils/constants";
|
||||
import {PayType, PayChannelEnum, SysCommonStatusEnum} from "@/utils/constants";
|
||||
import {getMerchantListByName} from "@/api/pay/merchant";
|
||||
import wechatJsApiForm from "@/views/pay/app/components/wechatJsApiForm";
|
||||
import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
|
||||
import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
"wechatJsApiForm": wechatJsApiForm
|
||||
"wechatChannelForm": wechatChannelForm,
|
||||
"aliPayChannelForm": aliPayChannelForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -243,16 +282,20 @@ export default {
|
|||
sysCommonStatusEnum: SysCommonStatusEnum,
|
||||
// 支付渠道枚举
|
||||
payChannelEnum: PayChannelEnum,
|
||||
// 支付类型
|
||||
payType: PayType,
|
||||
// 商户列表
|
||||
merchantList: [],
|
||||
// 是否显示支付窗口
|
||||
payOpen: false,
|
||||
// 微信组件传参参数
|
||||
wechatChannelParam: {
|
||||
channelParam: {
|
||||
// 是否修改
|
||||
"edit":false,
|
||||
// 是否显示
|
||||
"open":false,
|
||||
"edit": false,
|
||||
// 微信是否显示
|
||||
"wechatOpen": false,
|
||||
// 支付宝是否显示
|
||||
"aliPayOpen": false,
|
||||
// 应用ID
|
||||
"appId": null,
|
||||
// 渠道编码
|
||||
|
@ -279,7 +322,6 @@ export default {
|
|||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行查询
|
||||
getAppPage(params).then(response => {
|
||||
console.log(response.data);
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
|
@ -355,9 +397,9 @@ export default {
|
|||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateApp(this.form).then(response => {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -407,33 +449,47 @@ export default {
|
|||
*/
|
||||
handleGetMerchantListByName(name) {
|
||||
getMerchantListByName(name).then(response => {
|
||||
console.log(response)
|
||||
this.merchantList = response.data;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 修改支付渠道信息
|
||||
*/
|
||||
handleUpdateChannel(row, payCode) {
|
||||
this.wechatChannelParam.edit = true;
|
||||
this.wechatChannelParam.loading = true;
|
||||
this.wechatChannelParam.appId = row.id;
|
||||
this.wechatChannelParam.payCode = payCode;
|
||||
this.wechatChannelParam.payMerchant = row.payMerchant;
|
||||
this.wechatChannelParam.open = true;
|
||||
handleUpdateChannel(row, payCode, type) {
|
||||
this.settingChannelParam(row, payCode, type)
|
||||
this.channelParam.edit = true;
|
||||
this.channelParam.loading = true;
|
||||
|
||||
},
|
||||
/**
|
||||
* 新增支付渠道信息
|
||||
*/
|
||||
handleCreateChannel(row, payCode) {
|
||||
this.wechatChannelParam.edit = false;
|
||||
this.wechatChannelParam.loading = false;
|
||||
this.wechatChannelParam.appId = row.id;
|
||||
this.wechatChannelParam.payCode = payCode;
|
||||
this.wechatChannelParam.payMerchant = row.payMerchant;
|
||||
this.wechatChannelParam.open = true;
|
||||
handleCreateChannel(row, payCode, type) {
|
||||
this.settingChannelParam(row, payCode, type)
|
||||
this.channelParam.edit = false;
|
||||
this.channelParam.loading = false;
|
||||
|
||||
|
||||
},
|
||||
refreshTable(){
|
||||
/**
|
||||
* 设置支付渠道信息
|
||||
*/
|
||||
settingChannelParam(row, payCode, type) {
|
||||
if (type === PayType.WECHAT) {
|
||||
this.channelParam.wechatOpen = true;
|
||||
this.channelParam.aliPayOpen = false;
|
||||
}
|
||||
if (type === PayType.ALIPAY) {
|
||||
this.channelParam.aliPayOpen = true;
|
||||
this.channelParam.wechatOpen = false;
|
||||
}
|
||||
this.channelParam.edit = false;
|
||||
this.channelParam.loading = false;
|
||||
this.channelParam.appId = row.id;
|
||||
this.channelParam.payCode = payCode;
|
||||
this.channelParam.payMerchant = row.payMerchant;
|
||||
},
|
||||
refreshTable() {
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,21 +9,35 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
|||
*/
|
||||
public interface PayErrorCodeCoreConstants {
|
||||
|
||||
// ========== APP 模块 1-007-000-000 ==========
|
||||
/**
|
||||
* ========== APP 模块 1-007-000-000 ==========
|
||||
*/
|
||||
ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在");
|
||||
ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用");
|
||||
|
||||
// ========== CHANNEL 模块 1-007-001-000 ==========
|
||||
/**
|
||||
* ========== CHANNEL 模块 1-007-001-000 ==========
|
||||
*/
|
||||
ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在");
|
||||
ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用");
|
||||
ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在");
|
||||
|
||||
// ========== ORDER 模块 1-007-002-000 ==========
|
||||
ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在");
|
||||
ErrorCode CHANNEL_KEY_READ_ERROR = new ErrorCode(1007001004, "支付渠道秘钥文件读取失败");
|
||||
ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道");
|
||||
ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空");
|
||||
ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v3版本apiclient_key.pem不可为空");
|
||||
ErrorCode CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v3版本中apiclient_cert.pem不可为空");
|
||||
/**
|
||||
* ========== ORDER 模块 1-007-002-000 ==========
|
||||
*/
|
||||
ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在");
|
||||
ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付");
|
||||
ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付");
|
||||
ErrorCode PAY_ORDER_ERROR_USER = new ErrorCode(1007002003, "支付订单用户不正确");
|
||||
// ========== ORDER 模块(拓展单) 1-007-003-000 ==========
|
||||
|
||||
/**
|
||||
* ========== ORDER 模块(拓展单) 1-007-003-000 ==========
|
||||
*/
|
||||
ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在");
|
||||
ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
|
||||
ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007003002, "支付订单不处于已支付");
|
||||
|
@ -46,12 +60,4 @@ public interface PayErrorCodeCoreConstants {
|
|||
ErrorCode APP_NOT_EXISTS = new ErrorCode(1007005000, "支付应用信息不存在");
|
||||
|
||||
|
||||
/**
|
||||
* ========== 支付渠道 1-007-001-000 ==========
|
||||
*/
|
||||
ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在");
|
||||
ErrorCode CHANNEL_KEY_READ_ERROR = new ErrorCode(1007001004, "支付渠道秘钥文件读取失败");
|
||||
// TODO @aquan:下面这个错误码,缺了 CHANNEL 前缀。另外,错误码的分段,上面有啦,合并下进去哈
|
||||
ErrorCode EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道");
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ public class PayClientFactoryImpl implements PayClientFactory {
|
|||
case WX_APP: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
|
||||
case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config);
|
||||
case ALIPAY_QR: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
|
||||
case ALIPAY_APP: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
|
||||
case ALIPAY_PC: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
|
||||
}
|
||||
// 创建失败,错误日志 + 抛出异常
|
||||
log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", config);
|
||||
|
|
|
@ -3,7 +3,11 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
|
|||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
// TODO 芋艿:参数校验
|
||||
|
||||
/**
|
||||
* 支付宝的 PayClientConfig 实现类
|
||||
* 属性主要来自 {@link com.alipay.api.AlipayConfig} 的必要属性
|
||||
|
@ -25,11 +29,11 @@ public class AlipayPayClientConfig implements PayClientConfig {
|
|||
/**
|
||||
* 公钥类型 - 公钥模式
|
||||
*/
|
||||
private static final Integer MODE_PUBLIC_KEY = 1;
|
||||
public static final Integer MODE_PUBLIC_KEY = 1;
|
||||
/**
|
||||
* 公钥类型 - 证书模式
|
||||
*/
|
||||
private static final Integer MODE_CERTIFICATE = 2;
|
||||
public static final Integer MODE_CERTIFICATE = 2;
|
||||
|
||||
/**
|
||||
* 签名算法类型 - RSA
|
||||
|
@ -41,18 +45,21 @@ public class AlipayPayClientConfig implements PayClientConfig {
|
|||
* 1. {@link #SERVER_URL_PROD}
|
||||
* 2. {@link #SERVER_URL_SANDBOX}
|
||||
*/
|
||||
@NotBlank(message = "网关地址不能为空", groups = {ModePublicKey.class, ModeCertificate.class})
|
||||
private String serverUrl;
|
||||
|
||||
/**
|
||||
* 开放平台上创建的应用的 ID
|
||||
*/
|
||||
@NotBlank(message = "开放平台上创建的应用的 ID不能为空", groups = {ModePublicKey.class, ModeCertificate.class})
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 签名算法类型,推荐:RSA2
|
||||
*
|
||||
* <p>
|
||||
* {@link #SIGN_TYPE_DEFAULT}
|
||||
*/
|
||||
@NotBlank(message = "签名算法类型不能为空", groups = {ModePublicKey.class, ModeCertificate.class})
|
||||
private String signType;
|
||||
|
||||
/**
|
||||
|
@ -60,30 +67,43 @@ public class AlipayPayClientConfig implements PayClientConfig {
|
|||
* 1. {@link #MODE_PUBLIC_KEY} 情况,privateKey + alipayPublicKey
|
||||
* 2. {@link #MODE_CERTIFICATE} 情况,appCertContent + alipayPublicCertContent + rootCertContent
|
||||
*/
|
||||
@NotNull(message = "公钥类型不能为空", groups = {ModePublicKey.class, ModeCertificate.class})
|
||||
private Integer mode;
|
||||
|
||||
// ========== 公钥模式 ==========
|
||||
/**
|
||||
* 商户私钥
|
||||
*/
|
||||
@NotBlank(message = "商户私钥不能为空", groups = {ModePublicKey.class})
|
||||
private String privateKey;
|
||||
|
||||
/**
|
||||
* 支付宝公钥字符串
|
||||
*/
|
||||
@NotBlank(message = "支付宝公钥字符串不能为空", groups = {ModePublicKey.class})
|
||||
private String alipayPublicKey;
|
||||
|
||||
// ========== 证书模式 ==========
|
||||
/**
|
||||
* 指定商户公钥应用证书内容字符串
|
||||
*/
|
||||
@NotBlank(message = "指定商户公钥应用证书内容不能为空", groups = {ModeCertificate.class})
|
||||
private String appCertContent;
|
||||
/**
|
||||
* 指定支付宝公钥证书内容字符串
|
||||
*/
|
||||
@NotBlank(message = "指定支付宝公钥证书内容不能为空", groups = {ModeCertificate.class})
|
||||
private String alipayPublicCertContent;
|
||||
/**
|
||||
* 指定根证书内容字符串
|
||||
*/
|
||||
@NotBlank(message = "指定根证书内容字符串不能为空", groups = {ModeCertificate.class})
|
||||
private String rootCertContent;
|
||||
|
||||
public interface ModePublicKey {
|
||||
}
|
||||
|
||||
public interface ModeCertificate {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ import cn.hutool.core.io.IoUtil;
|
|||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
// TODO 芋艿:参数校验
|
||||
|
||||
/**
|
||||
* 微信支付的 PayClientConfig 实现类
|
||||
* 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性
|
||||
|
@ -20,13 +22,13 @@ public class WXPayClientConfig implements PayClientConfig {
|
|||
// TODO 芋艿:V2 or V3 客户端
|
||||
/**
|
||||
* API 版本 - V2
|
||||
*
|
||||
* <p>
|
||||
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1
|
||||
*/
|
||||
public static final String API_VERSION_V2 = "v2";
|
||||
/**
|
||||
* API 版本 - V3
|
||||
*
|
||||
* <p>
|
||||
* https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml
|
||||
*/
|
||||
public static final String API_VERSION_V3 = "v3";
|
||||
|
@ -34,14 +36,17 @@ public class WXPayClientConfig implements PayClientConfig {
|
|||
/**
|
||||
* 公众号或者小程序的 appid
|
||||
*/
|
||||
@NotBlank(message = "APPID 不能为空", groups = {V2.class, V3.class})
|
||||
private String appId;
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
@NotBlank(message = "商户号 不能为空", groups = {V2.class, V3.class})
|
||||
private String mchId;
|
||||
/**
|
||||
* API 版本
|
||||
*/
|
||||
@NotBlank(message = "API 版本 不能为空", groups = {V2.class, V3.class})
|
||||
private String apiVersion;
|
||||
|
||||
// ========== V2 版本的参数 ==========
|
||||
|
@ -49,33 +54,37 @@ public class WXPayClientConfig implements PayClientConfig {
|
|||
/**
|
||||
* 商户密钥
|
||||
*/
|
||||
@NotBlank(message = "商户密钥 不能为空", groups = {V2.class})
|
||||
private String mchKey;
|
||||
// /**
|
||||
// * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径.
|
||||
// * 对应的字符串
|
||||
// *
|
||||
// * 注意,可通过 {@link #main(String[])} 读取
|
||||
// */
|
||||
// private String keyContent;
|
||||
/**
|
||||
* apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径.
|
||||
* 对应的字符串
|
||||
*
|
||||
* 注意,可通过 {@link #main(String[])} 读取
|
||||
*/
|
||||
/// private String keyContent;
|
||||
|
||||
// ========== V3 版本的参数 ==========
|
||||
/**
|
||||
* apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径.
|
||||
* 对应的字符串
|
||||
*
|
||||
* <p>
|
||||
* 注意,可通过 {@link #main(String[])} 读取
|
||||
*/
|
||||
@NotBlank(message = "apiclient_key 不能为空", groups = {V3.class})
|
||||
private String privateKeyContent;
|
||||
/**
|
||||
* apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径.
|
||||
* 对应的字符串
|
||||
*
|
||||
* <p>
|
||||
* 注意,可通过 {@link #main(String[])} 读取
|
||||
*/
|
||||
@NotBlank(message = "apiclient_cert 不能为空", groups = {V3.class})
|
||||
private String privateCertContent;
|
||||
/**
|
||||
* apiV3 秘钥值
|
||||
*/
|
||||
@NotBlank(message = "apiV3 秘钥值 不能为空", groups = {V3.class})
|
||||
private String apiV3Key;
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException {
|
||||
|
@ -85,4 +94,17 @@ public class WXPayClientConfig implements PayClientConfig {
|
|||
System.out.println(IoUtil.readUtf8(new FileInputStream(path)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分组校验 v2版本
|
||||
*/
|
||||
public interface V2 {
|
||||
}
|
||||
|
||||
/**
|
||||
* 分组校验 v3版本
|
||||
*/
|
||||
public interface V3 {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ import lombok.Getter;
|
|||
public enum PayChannelEnum {
|
||||
|
||||
WX_PUB("wx_pub", "微信 JSAPI 支付"), // 公众号的网页
|
||||
// TODO @芋艿 这个地方你写的是 wx_lit 是不是少写了一个e? 还是我这里多加了一个e
|
||||
// TODO @aquan:这里就是 lite 哈,轻量
|
||||
WX_LITE("wx_lite","微信小程序支付"),
|
||||
WX_APP("wx_app", "微信 App 支付"),
|
||||
|
||||
|
@ -36,8 +34,38 @@ public enum PayChannelEnum {
|
|||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*/
|
||||
public static final String WECHAT = "WECHAT";
|
||||
|
||||
/**
|
||||
* 支付宝支付
|
||||
*/
|
||||
public static final String ALIPAY = "ALIPAY";
|
||||
|
||||
public static PayChannelEnum getByCode(String code) {
|
||||
return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前渠道是那种支付方式
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public static String verifyWechatOrAliPay(String code){
|
||||
switch (PayChannelEnum.getByCode(code)){
|
||||
case WX_PUB:
|
||||
case WX_LITE:
|
||||
case WX_APP:
|
||||
return WECHAT;
|
||||
case ALIPAY_PC:
|
||||
case ALIPAY_WAP:
|
||||
case ALIPAY_APP:
|
||||
case ALIPAY_QR:
|
||||
return ALIPAY;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue