mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 23:31:52 +08:00
增加支付相关表的 SQL,调整相关的实体
This commit is contained in:
parent
6e3aa8a752
commit
6dc65234ef
172
sql/pay2.sql
Normal file
172
sql/pay2.sql
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : 127.0.0.1
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 80026
|
||||
Source Host : localhost:3306
|
||||
Source Schema : ruoyi-vue-pro
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 80026
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 23/10/2021 17:46:45
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pay_app
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_app`;
|
||||
CREATE TABLE `pay_app` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '应用编号',
|
||||
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '应用名',
|
||||
`status` tinyint NOT NULL COMMENT '开启状态',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`pay_notify_url` varchar(1024) NOT NULL COMMENT '支付结果的回调地址',
|
||||
`notify_notify_url` varchar(1024) NOT NULL COMMENT '退款结果的回调地址',
|
||||
`merchant_id` bigint NOT NULL COMMENT '商户编号',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付应用信息';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_app
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `pay_app` VALUES (6, '芋道', 0, '我是一个公众号', 'http://127.0.0.1', 'http://127.0.0.1', 1, '', '2021-10-23 08:49:25', '', '2021-10-23 08:49:25', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pay_channel
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_channel`;
|
||||
CREATE TABLE `pay_channel` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商户编号',
|
||||
`code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道编码',
|
||||
`status` tinyint NOT NULL COMMENT '开启状态',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`fee_rate` double NOT NULL DEFAULT '0' COMMENT '渠道费率,单位:百分比',
|
||||
`merchant_id` bigint NOT NULL COMMENT '商户编号',
|
||||
`app_id` bigint NOT NULL COMMENT '应用编号',
|
||||
`config` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '支付渠道配置',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付渠道\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_channel
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `pay_channel` VALUES (9, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig\",\"appId\":\"wx041349c6f39b268b\",\"mchId\":\"1545083881\",\"apiVersion\":\"v2\",\"mchKey\":\"0alL64UDQdlCwiKZ73ib7ypaIjMns06p\",\"privateKeyContent\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5q2hYE3loOQoH\\nl/2kh/epuj17W8VpV5vBl7ysJWAbBXux6mlq4gKTHD0QUQdiKtDEUm/bKC9Bi6VU\\nuklM5Y8oCaCbhjklHRbET8jsgd9phSNGviHclYRLsQRO8oXnN89kN0y7DYKm0hYd\\nmaiS12Z3v8VaImSTr4HVeHlC/z3S6mdwSr263stKt931YTcbTj/QFH7znsv9Na0u\\nX6LaMBEEAsJctWdm8Ndrd1tGh9Fzf0DA5VRXsJR3kkWspy+IwiDTPV/FDKOU9NJC\\nSxMmDePerTfkoZ2s1rltqBK0ykDJrXtxR+hTzEsKZ/KpNi8tyYpfNZsviHIlUsLP\\nFJ5UvUhpAgMBAAECggEAd90NltazqTIxpGdeCwrwOzWNnYbIclJprlhMKIJUgf1P\\nNrPTbHoOGXTAgzkcYCat8iAaMEzH/TOu/3zn92m3uqxEcEL9v1UBLqknWHAbkB6w\\ngGocqDAqYUcdNe5hvbyM+fCta5C0SQgV2PQrHOlMMICwYpkTfzhtxCdreXIYMoGg\\nJEIRkZWgrm/N7LTtNgizznuUjy6OURWjXaWKPcs3b3j6G1gLj9Vp++z4y0u51nqM\\n4R6fcvl8M6BjlcC8zo6DbOvCW8cXtuXsnru+2TPrUnsGeybJok4fEQsfW1BvpvPo\\nief38rYJn4OWxIrHcpWrhNtXtgRPeiMGFfIsEQDmVQKBgQDzXK6Nn3Nr3TFfGVTy\\n8QYrzOuY2NqzH8nnsLL6qn3HoKxTv+PcFKOTPsi6f4hIYCzBP0esRrPv0ffMu9oQ\\nJvFtCJvMmcKGtp0Q5hcj0y/XkbC3AWuahJtBv8lhKXVnQXSL0j3+ombljw4/8yN0\\nAzgBz+j/skQQgZ3sN5h+DHGtgwKBgQDDT784/2pd4m86c/uBmrwYfqu6MJo0eHJh\\n1XPtE+u8pOHyNTFk77rKobKDqN5VlrF0uEmBc/08LKhyxJ3vh/zAbcmqT1Mq778y\\nAKKUtVmvcaVDrvSQHsnhj0zt4SHGmmU34U2b9hV+nocq5VszX6/jp//HJi9bs3We\\ndAzfFCmaowKBgC1MmDVGc+6lCraf+X8LPFHU4Bnga70h8qxM6NPd/nG1R76DHn/t\\n25DiA+0rJgwK0unZxJadxoqic9TJNssA5Lmd+5o3GM2Imm311mLVwbcHqHQ4MHZf\\nrqKrd2m9lNv2hCIurVmDk1Gxsj5XHMdQfhFgSQengCHubp30r07vNA3PAoGAUEAE\\nIjdQTSMs8KeXP7mEb8wcY3R05/pVhT1fVJpK0kgtTofss7yM05V88/v+3sv8Pik6\\niqZN9tuimwWOn00Q3UA/DGtrkMjRlooMQ24AW8YmUZkhg9YivTtUMKnAZwopbLx2\\nVw7V5iDdCRMUVheK/c+ZmQpnixZBzcmBQGfYcGECgYBjEq3Mem+Aw6pXOu6+0FwH\\n9y6Xi4HhBkq0OOZZuXFtWVry7YrD3pBgzWVAZJqJCkyPKKZzCzwdbFd3u0lYBs35\\nzYgx7ug4hR+wfI980a3vxjcWGOqnOUUnUJ7ucIa+KDgnYV/bBy4jqpVreXmWAJXl\\nfyjG3eLWBrtrsI9YX6zeAA==\\n-----END PRIVATE KEY-----\\n\",\"privateCertContent\":\"-----BEGIN CERTIFICATE-----\\nMIID6TCCAtGgAwIBAgIUNkEHq6aQcF80NSYqWS58ybsJzI4wDQYJKoZIhvcNAQEL\\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\nQ0EwHhcNMjExMDIxMDU0NTQxWhcNMjYxMDIwMDU0NTQxWjB7MRMwEQYDVQQDDAox\\nNTQ1MDgzODgxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM\\nHuWOhuWfjuWMuuWkp+adjuWwp+aXpeeUqOWTgeW6lzELMAkGA1UEBgwCQ04xETAP\\nBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\nuatoWBN5aDkKB5f9pIf3qbo9e1vFaVebwZe8rCVgGwV7seppauICkxw9EFEHYirQ\\nxFJv2ygvQYulVLpJTOWPKAmgm4Y5JR0WxE/I7IHfaYUjRr4h3JWES7EETvKF5zfP\\nZDdMuw2CptIWHZmoktdmd7/FWiJkk6+B1Xh5Qv890upncEq9ut7LSrfd9WE3G04/\\n0BR+857L/TWtLl+i2jARBALCXLVnZvDXa3dbRofRc39AwOVUV7CUd5JFrKcviMIg\\n0z1fxQyjlPTSQksTJg3j3q035KGdrNa5bagStMpAya17cUfoU8xLCmfyqTYvLcmK\\nXzWbL4hyJVLCzxSeVL1IaQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMC\\nBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1\\nYmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\\nMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBe7XgncAY/1PLbCsnMsYt11k3V\\n2cdNZ+yuCxhlOEKk3nHE6WCTL6zL0qWlTKKpnw1rE/+4OS76Tg72wWXcHfHDAOgt\\n9icp62cKx1WO3QweeZpSvLDmtdLgKKrqeIWh+rL8+ZhuAOxSkaRwcsMTWDaLeDOi\\n0pGeqvfG8WNhPxkkaSI8xbiTK641Yg9WT/Q4yfHS7Q6wg1dj9YQdo0dvVB0S2Nir\\nX9IK6PUaHDnQeFKDmKgLkDGLaKaiijEvC91wMEE6qB8b0eNhciaxq2YhGHcFmSRP\\nWUyc5CmBadt7wIOH5Z3bfuwWGxqxKjNw/baM/d+nk7hlDr01YL9c0g16B9MW\\n-----END CERTIFICATE-----\\n\",\"apiV3Key\":\"joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase\"}', NULL, '2021-10-23 17:12:10', NULL, '2021-10-23 17:12:10', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pay_merchant
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_merchant`;
|
||||
CREATE TABLE `pay_merchant` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商户编号',
|
||||
`no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商户号',
|
||||
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商户全称',
|
||||
`short_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商户简称',
|
||||
`status` tinyint NOT NULL COMMENT '开启状态',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付商户信息';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_merchant
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `pay_merchant` VALUES (1, 'M233666999', '芋道源码', '芋艿', 0, '我是备注', '', '2021-10-23 08:31:14', '', '2021-10-23 08:44:04', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pay_order
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_order`;
|
||||
CREATE TABLE `pay_order` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付订单编号',
|
||||
`merchant_id` bigint NOT NULL COMMENT '商户编号',
|
||||
`app_id` bigint NOT NULL COMMENT '应用编号',
|
||||
`channel_id` bigint NOT NULL COMMENT '渠道编号',
|
||||
`channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道编码',
|
||||
`merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号',
|
||||
`subject` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品标题',
|
||||
`body` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品描述',
|
||||
`amount` bigint NOT NULL COMMENT '支付金额,单位:分',
|
||||
`channel_fee_rate` double NOT NULL DEFAULT '0' COMMENT '渠道手续费,单位:百分比',
|
||||
`channel_fee_amount` bigint NOT NULL DEFAULT '0' COMMENT '渠道手续金额,单位:分',
|
||||
`status` tinyint NOT NULL COMMENT '支付状态',
|
||||
`notify_status` tinyint NOT NULL COMMENT '通知商户支付结果的回调状态',
|
||||
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户 IP',
|
||||
`expire_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '订单失效时间',
|
||||
`success_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '订单支付成功时间',
|
||||
`success_extension_id` bigint DEFAULT NULL COMMENT '支付成功的订单拓展单编号',
|
||||
`channel_extras` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '支付渠道的额外参数',
|
||||
`notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '异步通知地址',
|
||||
`refund_status` tinyint NOT NULL COMMENT '退款状态',
|
||||
`refund_times` tinyint NOT NULL COMMENT '退款次数',
|
||||
`refund_amount` bigint NOT NULL COMMENT '退款总金额,单位:分',
|
||||
`channel_user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '渠道用户编号',
|
||||
`channel_order_no` varchar(64) DEFAULT NULL COMMENT '渠道订单号',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付订单\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_order
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pay_order_extension
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pay_order_extension`;
|
||||
CREATE TABLE `pay_order_extension` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付订单编号',
|
||||
`no` varchar(64) NOT NULL COMMENT '支付订单号',
|
||||
`order_id` bigint NOT NULL COMMENT '支付订单编号',
|
||||
`channel_id` bigint NOT NULL COMMENT '渠道编号',
|
||||
`channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道编码',
|
||||
`channel_callback_data` varchar(1024) NOT NULL COMMENT '支付渠道异步通知的内容',
|
||||
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户 IP',
|
||||
`status` tinyint NOT NULL COMMENT '支付状态',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付订单\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_order_extension
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `pay_order_extension` VALUES (9, '', 1, 0, '', '2021-10-23 09:27:37', '', 0, NULL, '2021-10-23 17:12:10', NULL, '2021-10-23 17:12:10', b'0');
|
||||
COMMIT;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
@ -11,7 +11,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信渠道Service接口
|
||||
* 短信渠道 Service 接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 9:24
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@ -16,4 +17,6 @@ public interface PayOrderCoreConvert {
|
||||
|
||||
PayOrderExtensionDO convert(PayOrderSubmitReqDTO bean);
|
||||
|
||||
PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqDTO bean);
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 支付应用 DO
|
||||
@ -14,7 +15,13 @@ import lombok.Data;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("pay_app")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayAppDO extends BaseDO {
|
||||
|
||||
/**
|
||||
@ -36,11 +43,6 @@ public class PayAppDO extends BaseDO {
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 应用私钥
|
||||
* TODO 芋艿:用途
|
||||
*/
|
||||
private String secret;
|
||||
/**
|
||||
* 支付结果的回调地址
|
||||
*/
|
||||
|
@ -1,9 +1,13 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 支付渠道 DO
|
||||
@ -14,6 +18,12 @@ import lombok.Data;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "pay_channel", autoResultMap = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayChannelDO extends BaseDO {
|
||||
|
||||
/**
|
||||
@ -48,8 +58,11 @@ public class PayChannelDO extends BaseDO {
|
||||
*
|
||||
* 关联 {@link PayAppDO#getId()}
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
// TODO 芋艿:不同渠道的配置。暂时考虑硬编码
|
||||
private Long appId;
|
||||
/**
|
||||
* 支付渠道配置
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private PayClientConfig config;
|
||||
|
||||
}
|
||||
|
@ -3,15 +3,22 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 商户信息 DO
|
||||
* 支付商户信息 DO
|
||||
* 目前暂时没有特别的用途,主要为未来多商户提供基础。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName("pay_merchant")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayMerchantDO extends BaseDO {
|
||||
|
||||
/**
|
||||
|
@ -3,15 +3,16 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付订单 DO
|
||||
@ -22,6 +23,9 @@ import java.util.Date;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayOrderDO extends BaseDO {
|
||||
|
||||
/**
|
||||
@ -68,10 +72,10 @@ public class PayOrderDO extends BaseDO {
|
||||
* 商品描述信息
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 商户拓展参数
|
||||
*/
|
||||
private String merchantExtra;
|
||||
// /**
|
||||
// * 商户拓展参数
|
||||
// */
|
||||
// private Map<String, String> merchantExtras;
|
||||
|
||||
// ========== 订单相关字段 ==========
|
||||
|
||||
@ -80,13 +84,13 @@ public class PayOrderDO extends BaseDO {
|
||||
*/
|
||||
private Long amount;
|
||||
/**
|
||||
* 渠道手续费
|
||||
* 渠道手续费,单位:百分比
|
||||
*
|
||||
* 冗余 {@link PayChannelDO#getFeeRate()}
|
||||
*/
|
||||
private Double channelFeeRate;
|
||||
/**
|
||||
* 渠道手续金额
|
||||
* 渠道手续金额,单位:分
|
||||
*/
|
||||
private Long channelFeeAmount;
|
||||
/**
|
||||
@ -101,47 +105,34 @@ public class PayOrderDO extends BaseDO {
|
||||
*/
|
||||
private Integer notifyStatus;
|
||||
/**
|
||||
* 客户端 IP
|
||||
* 用户 IP
|
||||
*/
|
||||
private String clientIp;
|
||||
/**
|
||||
* 订单支付成功时间
|
||||
*/
|
||||
private Date successTime;
|
||||
private String userIp;
|
||||
/**
|
||||
* 订单失效时间
|
||||
*/
|
||||
private Date expireTime;
|
||||
/**
|
||||
* 支付渠道的额外参数
|
||||
*
|
||||
* 参见 https://www.pingxx.com/api/支付渠道%20extra%20参数说明.html
|
||||
* 订单支付成功时间
|
||||
*/
|
||||
private String channelExtra;
|
||||
/**
|
||||
* 异步通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
/**
|
||||
* 页面跳转地址
|
||||
*/
|
||||
private String returnUrl;
|
||||
private Date successTime;
|
||||
/**
|
||||
* 支付成功的订单拓展单编号
|
||||
*
|
||||
* 关联 {@link PayOrderDO#getId()}
|
||||
*/
|
||||
private Long successExtensionId;
|
||||
|
||||
// TODO 芋艿:可能要优化
|
||||
/**
|
||||
* 渠道支付错误码
|
||||
* 支付渠道的额外参数
|
||||
*
|
||||
* 参见 https://www.pingxx.com/api/支付渠道%20extra%20参数说明.html
|
||||
*/
|
||||
private String errorCode;
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private Map<String, String> channelExtras;
|
||||
/**
|
||||
* 渠道支付错误消息
|
||||
* 异步通知地址
|
||||
*/
|
||||
private String errorMessage;
|
||||
private String notifyUrl;
|
||||
|
||||
// ========== 退款相关字段 ==========
|
||||
/**
|
||||
|
@ -4,9 +4,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChann
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 支付订单拓展 DO
|
||||
@ -17,7 +15,10 @@ import lombok.experimental.Accessors;
|
||||
@TableName("pay_order_extension")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayOrderExtensionDO extends BaseDO {
|
||||
|
||||
/**
|
||||
@ -25,7 +26,7 @@ public class PayOrderExtensionDO extends BaseDO {
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 订单号,根据规则生成
|
||||
* 支付订单号,根据规则生成
|
||||
* 调用支付渠道时,使用该字段作为对接的订单号。
|
||||
* 1. 调用微信支付 https://api.mch.weixin.qq.com/pay/unifiedorder 时,使用该字段作为 out_trade_no
|
||||
* 2. 调用支付宝 https://opendocs.alipay.com/apis 时,使用该字段作为 out_trade_no
|
||||
@ -50,9 +51,9 @@ public class PayOrderExtensionDO extends BaseDO {
|
||||
*/
|
||||
private Integer channelCode;
|
||||
/**
|
||||
* 客户端 IP
|
||||
* 用户 IP
|
||||
*/
|
||||
private String clientIp;
|
||||
private String userIp;
|
||||
/**
|
||||
* 支付状态
|
||||
*
|
||||
|
@ -67,10 +67,10 @@ public class PayRefundDO extends BaseDO {
|
||||
* 例如说,内部系统 A 的退款订单号。需要保证每个 PayMerchantDO 唯一 TODO 芋艿:需要在测试下
|
||||
*/
|
||||
private String merchantRefundNo;
|
||||
/**
|
||||
* 商户拓展参数
|
||||
*/
|
||||
private String merchantExtra;
|
||||
// /**
|
||||
// * 商户拓展参数
|
||||
// */
|
||||
// private String merchantExtra;
|
||||
|
||||
// ========== 退款相关字段 ==========
|
||||
/**
|
||||
@ -85,9 +85,9 @@ public class PayRefundDO extends BaseDO {
|
||||
*/
|
||||
private Integer notifyStatus;
|
||||
/**
|
||||
* 客户端 IP
|
||||
* 用户 IP
|
||||
*/
|
||||
private String clientIp;
|
||||
private String userIp;
|
||||
/**
|
||||
* 退款金额,单位:分
|
||||
*/
|
||||
@ -115,16 +115,6 @@ public class PayRefundDO extends BaseDO {
|
||||
*/
|
||||
private String notifyUrl;
|
||||
|
||||
// TODO 芋艿:可能要优化
|
||||
/**
|
||||
* 渠道支付错误码
|
||||
*/
|
||||
private String errorCode;
|
||||
/**
|
||||
* 渠道支付错误消息
|
||||
*/
|
||||
private String errorMessage;
|
||||
|
||||
// ========== 渠道相关字段 ==========
|
||||
/**
|
||||
* 渠道订单号
|
||||
|
@ -3,6 +3,9 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Mapper
|
||||
public interface PayChannelCoreMapper extends BaseMapperX<PayChannelDO> {
|
||||
@ -11,4 +14,7 @@ public interface PayChannelCoreMapper extends BaseMapperX<PayChannelDO> {
|
||||
return selectOne("app_id", appId, "code", code);
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM pay_channel WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package cn.iocoder.yudao.coreservice.modules.pay.enums;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* Pay 错误码枚举类
|
||||
* Pay 错误码 Core 枚举类
|
||||
*
|
||||
* pay 系统,使用 1-007-000-000 段
|
||||
*/
|
||||
public interface PayErrorCodeConstants {
|
||||
public interface PayErrorCodeCoreConstants {
|
||||
|
||||
// ========== APP 模块 1-007-000-000 ==========
|
||||
ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在");
|
||||
@ -15,7 +15,8 @@ public interface PayErrorCodeConstants {
|
||||
|
||||
// ========== CHANNEL 模块 1-007-001-000 ==========
|
||||
ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在");
|
||||
ErrorCode PAY_CHANNEL_IS_DISABLE = 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 PAY_ORDER_NOT_FOUND = new ErrorCode(100401000, "支付订单不存在");
|
@ -10,6 +10,11 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
*/
|
||||
public interface PayChannelCoreService {
|
||||
|
||||
/**
|
||||
* 初始化支付客户端
|
||||
*/
|
||||
void initPayClients();
|
||||
|
||||
/**
|
||||
* 支付渠道的合法性
|
||||
*
|
||||
|
@ -10,7 +10,7 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
|
@ -1,17 +1,25 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant.PayChannelCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeConstants;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeConstants.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
@ -24,9 +32,67 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
||||
@Slf4j
|
||||
public class PayChannelCoreServiceImpl implements PayChannelCoreService {
|
||||
|
||||
/**
|
||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
||||
*/
|
||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
||||
*/
|
||||
private volatile Date maxUpdateTime;
|
||||
|
||||
@Resource
|
||||
private PayChannelCoreMapper payChannelCoreMapper;
|
||||
|
||||
@Resource
|
||||
private PayClientFactory payClientFactory;
|
||||
|
||||
@Override
|
||||
public void initPayClients() {
|
||||
// 获取支付渠道,如果有更新
|
||||
List<PayChannelDO> payChannels = this.loadPayChannelIfUpdate(maxUpdateTime);
|
||||
if (CollUtil.isEmpty(payChannels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建或更新支付 Client
|
||||
payChannels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),
|
||||
payChannel.getCode(), payChannel.getConfig()));
|
||||
|
||||
// 写入缓存
|
||||
assert payChannels.size() > 0; // 断言,避免告警
|
||||
maxUpdateTime = payChannels.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime();
|
||||
log.info("[initPayClients][初始化 PayChannel 数量为 {}]", payChannels.size());
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
||||
public void schedulePeriodicRefresh() {
|
||||
initPayClients();
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果支付渠道发生变化,从数据库中获取最新的全量支付渠道。
|
||||
* 如果未发生变化,则返回空
|
||||
*
|
||||
* @param maxUpdateTime 当前支付渠道的最大更新时间
|
||||
* @return 支付渠道列表
|
||||
*/
|
||||
private List<PayChannelDO> loadPayChannelIfUpdate(Date maxUpdateTime) {
|
||||
// 第一步,判断是否要更新。
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadPayChannelIfUpdate][首次加载全量支付渠道]");
|
||||
} else { // 判断数据库中是否有更新的支付渠道
|
||||
if (payChannelCoreMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadPayChannelIfUpdate][增量加载全量支付渠道]");
|
||||
}
|
||||
// 第二步,如果有更新,则从数据库加载所有支付渠道
|
||||
return payChannelCoreMapper.selectList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayChannelDO validPayChannel(Long appId, String code) {
|
||||
PayChannelDO channel = payChannelCoreMapper.selectByAppIdAndCode(appId, code);
|
||||
@ -34,7 +100,7 @@ public class PayChannelCoreServiceImpl implements PayChannelCoreService {
|
||||
throw exception(PAY_CHANNEL_NOT_FOUND);
|
||||
}
|
||||
if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) {
|
||||
throw exception(PayErrorCodeConstants.PAY_CHANNEL_IS_DISABLE);
|
||||
throw exception(PayErrorCodeCoreConstants.PAY_CHANNEL_IS_DISABLE);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ public class PayOrderCreateReqDTO implements Serializable {
|
||||
@NotEmpty(message = "应用编号不能为空")
|
||||
private Long appId;
|
||||
/**
|
||||
* 客户端 IP
|
||||
* 用户 IP
|
||||
*/
|
||||
@NotEmpty(message = "客户端 IP 不能为空")
|
||||
private String clientIp;
|
||||
@NotEmpty(message = "用户 IP 不能为空")
|
||||
private String userIp;
|
||||
|
||||
// ========== 商户相关字段 ==========
|
||||
|
||||
@ -40,7 +40,7 @@ public class PayOrderCreateReqDTO implements Serializable {
|
||||
@Length(max = 32, message = "商品标题不能超过 32")
|
||||
private String subject;
|
||||
/**
|
||||
* 商品描述信息
|
||||
* 商品描述
|
||||
*/
|
||||
@NotEmpty(message = "商品描述信息不能为空")
|
||||
@Length(max = 128, message = "商品描述信息长度不能超过128")
|
||||
|
@ -33,9 +33,9 @@ public class PayOrderSubmitReqDTO implements Serializable {
|
||||
private String channelCode;
|
||||
|
||||
/**
|
||||
* 客户端 IP
|
||||
* 用户 IP
|
||||
*/
|
||||
@NotEmpty(message = "客户端 IP 不能为空")
|
||||
private String clientIp;
|
||||
@NotEmpty(message = "用户 IP 不能为空")
|
||||
private String userIp;
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmit
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -25,8 +27,7 @@ import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeConstants.PAY_ORDER_NOT_FOUND;
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING;
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
@ -44,6 +45,9 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
@Resource
|
||||
private PayChannelCoreService payChannelCoreService;
|
||||
|
||||
@Resource
|
||||
private PayClientFactory payClientFactory;
|
||||
|
||||
@Resource
|
||||
private PayOrderCoreMapper payOrderCoreMapper;
|
||||
@Resource
|
||||
@ -79,6 +83,12 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
PayAppDO app = payAppCoreService.validPayApp(reqDTO.getId());
|
||||
// 校验支付渠道是否有效
|
||||
PayChannelDO channel = payChannelCoreService.validPayChannel(reqDTO.getId(), reqDTO.getChannelCode());
|
||||
// 校验支付客户端是否正确初始化
|
||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||
if (client == null) {
|
||||
log.error("[submitPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 获得 PayOrderDO ,并校验其是否存在
|
||||
PayOrderDO order = payOrderCoreMapper.selectById(reqDTO.getId());
|
||||
@ -96,13 +106,14 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
payOrderExtensionCoreMapper.insert(orderExtension);
|
||||
|
||||
// 调用三方接口
|
||||
AbstractThirdPayClient thirdPayClient = ThirdPayClientFactory.getThirdPayClient(submitReqDTO.getPayChannel());
|
||||
CommonResult<String> invokeResult = thirdPayClient.submitTransaction(payTransaction, orderExtension, null); // TODO 暂时传入 extra = null
|
||||
// TODO 暂时传入 extra = null
|
||||
CommonResult<?> invokeResult = client.unifiedOrder(PayOrderCoreConvert.INSTANCE.convert2(reqDTO));
|
||||
invokeResult.checkError();
|
||||
|
||||
// TODO 轮询三方接口,是否已经支付的任务
|
||||
// 返回成功
|
||||
return new PayOrderSubmitRespDTO().setExtensionId(orderExtension.getId()).setInvokeResponse(invokeResult.getData());
|
||||
return new PayOrderSubmitRespDTO().setExtensionId(orderExtension.getId())
|
||||
.setInvokeResponse(JsonUtils.toJsonString(invokeResult));
|
||||
}
|
||||
|
||||
private String generateOrderExtensionNo() {
|
||||
|
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.coreservice;
|
||||
|
||||
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class)
|
||||
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
|
||||
public class BaseDbAndRedisIntegrationTest {
|
||||
|
||||
@Import({
|
||||
// DB 配置类
|
||||
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
|
||||
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
|
||||
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
|
||||
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
|
||||
// MyBatis 配置类
|
||||
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
|
||||
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
|
||||
|
||||
// Redis 配置类
|
||||
RedisAutoConfiguration.class, // Spring Redis 自动配置类
|
||||
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
|
||||
RedissonAutoConfiguration.class, // Redisson 自动高配置类
|
||||
})
|
||||
public static class Application {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.coreservice;
|
||||
|
||||
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbIntegrationTest.Application.class)
|
||||
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
|
||||
public class BaseDbIntegrationTest {
|
||||
|
||||
@Import({
|
||||
// DB 配置类
|
||||
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
|
||||
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
|
||||
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
|
||||
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
|
||||
// MyBatis 配置类
|
||||
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
|
||||
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
|
||||
})
|
||||
public static class Application {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.coreservice;
|
||||
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class)
|
||||
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
|
||||
public class BaseRedisIntegrationTest {
|
||||
|
||||
@Import({
|
||||
// Redis 配置类
|
||||
RedisAutoConfiguration.class, // Spring Redis 自动配置类
|
||||
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
|
||||
RedissonAutoConfiguration.class, // Redisson 自动高配置类
|
||||
})
|
||||
public static class Application {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class PayChannelDOTest {
|
||||
|
||||
@Test
|
||||
public void testSerialization() {
|
||||
PayChannelDO payChannelDO = new PayChannelDO();
|
||||
// 创建配置
|
||||
WXPayClientConfig config = new WXPayClientConfig();
|
||||
config.setAppId("wx041349c6f39b268b");
|
||||
config.setMchId("1545083881");
|
||||
config.setApiVersion(WXPayClientConfig.API_VERSION_V2);
|
||||
config.setMchKey("0alL64UDQdlCwiKZ73ib7ypaIjMns06p");
|
||||
payChannelDO.setConfig(config);
|
||||
|
||||
// 序列化
|
||||
String text = JsonUtils.toJsonString(payChannelDO);
|
||||
System.out.println(text);
|
||||
|
||||
// 反序列化
|
||||
payChannelDO = JsonUtils.parseObject(text, PayChannelDO.class);
|
||||
System.out.println(payChannelDO.getConfig().getClass());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.iocoder.yudao.coreservice.BaseDbAndRedisIntegrationTest;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.List;
|
||||
|
||||
@Resource
|
||||
public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest {
|
||||
|
||||
@Resource
|
||||
private PayChannelCoreMapper payChannelCoreMapper;
|
||||
|
||||
/**
|
||||
* 插入初始配置
|
||||
*/
|
||||
@Test
|
||||
public void testInsert() throws FileNotFoundException {
|
||||
PayChannelDO payChannelDO = new PayChannelDO();
|
||||
payChannelDO.setCode(PayChannelEnum.WX_PUB.getCode());
|
||||
payChannelDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
payChannelDO.setFeeRate(1D);
|
||||
payChannelDO.setMerchantId(1L);
|
||||
payChannelDO.setAppId(6L);
|
||||
// 配置
|
||||
WXPayClientConfig config = new WXPayClientConfig();
|
||||
config.setAppId("wx041349c6f39b268b");
|
||||
config.setMchId("1545083881");
|
||||
config.setApiVersion(WXPayClientConfig.API_VERSION_V2);
|
||||
config.setMchKey("0alL64UDQdlCwiKZ73ib7ypaIjMns06p");
|
||||
config.setPrivateKeyContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_key.pem")));
|
||||
config.setPrivateCertContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem")));
|
||||
config.setApiV3Key("joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase");
|
||||
payChannelDO.setConfig(config);
|
||||
// 执行插入
|
||||
payChannelCoreMapper.insert(payChannelDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有支付配置,看看是否都是 ok 的
|
||||
*/
|
||||
@Test
|
||||
public void testSelectList() {
|
||||
List<PayChannelDO> payChannels = payChannelCoreMapper.selectList();
|
||||
System.out.println(payChannels.size());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
spring:
|
||||
main:
|
||||
lazy-initialization: true # 开启懒加载,加快速度
|
||||
banner-mode: off # 单元测试,禁用 Banner
|
||||
|
||||
--- #################### 数据库相关配置 ####################
|
||||
|
||||
spring:
|
||||
# 数据源配置项
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
dynamic: # 多数据源配置
|
||||
druid: # Druid 【连接池】相关的全局配置
|
||||
initial-size: 5 # 初始连接数
|
||||
min-idle: 10 # 最小连接池数量
|
||||
max-active: 20 # 最大连接池数量
|
||||
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
|
||||
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
|
||||
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
|
||||
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
|
||||
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: 123456
|
||||
slave: # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: 123456
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 0 # 数据库索引
|
||||
|
||||
mybatis:
|
||||
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: AUTO # 自增 ID
|
||||
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
|
||||
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
|
||||
mapper-locations: classpath*:mapper/*.xml
|
||||
type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject, ${yudao.core-service.base-package}.modules.*.dal.dataobject
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
--- #################### 配置中心相关配置 ####################
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||
|
||||
# Resilience4j 配置项
|
||||
resilience4j:
|
||||
ratelimiter:
|
||||
instances:
|
||||
backendA:
|
||||
limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
|
||||
limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
|
||||
timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
|
||||
register-health-indicator: true # 是否注册到健康监测
|
||||
|
||||
--- #################### 监控相关配置 ####################
|
||||
|
||||
--- #################### 芋道相关配置 ####################
|
||||
|
||||
yudao:
|
||||
info:
|
||||
version: 1.0.0
|
||||
base-package: cn.iocoder.yudao.adminserver
|
||||
core-service:
|
||||
base-package: cn.iocoder.yudao.coreservice
|
@ -22,6 +22,12 @@
|
||||
<artifactId>yudao-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring 核心 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
@ -47,16 +53,6 @@
|
||||
</dependency>
|
||||
|
||||
<!-- 三方云服务相关 -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.github.javen205</groupId>-->
|
||||
<!-- <artifactId>IJPay-AliPay</artifactId>-->
|
||||
<!-- <version>2.7.8</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.github.javen205</groupId>-->
|
||||
<!-- <artifactId>IJPay-WxPay</artifactId>-->
|
||||
<!-- <version>2.7.8</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.framework.pay.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 支付配置类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Configuration
|
||||
public class YudaoPayAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public PayClientFactory payClientFactory() {
|
||||
return new PayClientFactoryImpl();
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,16 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* 支付客户端的配置,本质是支付渠道的配置
|
||||
* 每个不同的渠道,需要不同的配置,通过子类来定义
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
// @JsonTypeInfo 注解的作用,Jackson 多态
|
||||
// 1. 序列化到时数据库时,增加 @class 属性。
|
||||
// 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型
|
||||
public interface PayClientConfig {
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ import java.util.Date;
|
||||
public class PayOrderUnifiedReqDTO {
|
||||
|
||||
/**
|
||||
* 客户端 IP
|
||||
* 用户 IP
|
||||
*/
|
||||
@NotEmpty(message = "客户端 IP 不能为空")
|
||||
private String clientIp;
|
||||
@NotEmpty(message = "用户 IP 不能为空")
|
||||
private String userIp;
|
||||
|
||||
// ========== 商户相关字段 ==========
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig>
|
||||
model.setSubject(reqDTO.getSubject());
|
||||
model.setBody(reqDTO.getBody());
|
||||
model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString()); // 单位:元
|
||||
// TODO 芋艿:clientIp + expireTime
|
||||
// TODO 芋艿:userIp + expireTime
|
||||
// 构建 AlipayTradePrecreateRequest
|
||||
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
|
||||
request.setBizModel(model);
|
||||
|
@ -46,7 +46,7 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
|
||||
model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString());
|
||||
model.setProductCode("QUICK_WAP_PAY"); // TODO 芋艿:这里咋整
|
||||
model.setSellerId("2088102147948060"); // TODO 芋艿:这里咋整
|
||||
// TODO 芋艿:clientIp + expireTime
|
||||
// TODO 芋艿:userIp + expireTime
|
||||
// 构建 AlipayTradeWapPayRequest
|
||||
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
|
||||
request.setBizModel(model);
|
||||
|
Loading…
Reference in New Issue
Block a user