7.19 拼团成功回调添加MQ消息通知方式,同时兼容原来http方式
This commit is contained in:
parent
0f22083d28
commit
39d3230bfd
276
docs/dev-ops/mysql/sql/0719group_buying_sys.sql
Normal file
276
docs/dev-ops/mysql/sql/0719group_buying_sys.sql
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : group_buy_local
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 80042
|
||||
Source Host : localhost:13306
|
||||
Source Schema : group_buying_sys
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 80042
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 19/07/2025 18:10:09
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for crowd_tags
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `crowd_tags`;
|
||||
CREATE TABLE `crowd_tags` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群ID',
|
||||
`tag_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群名称',
|
||||
`tag_desc` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群描述',
|
||||
`statistics` int NOT NULL COMMENT '人群标签统计量',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_tag_id`(`tag_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '人群标签' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of crowd_tags
|
||||
-- ----------------------------
|
||||
INSERT INTO `crowd_tags` VALUES (1, 'RQ_KJHKL98UU78H66554GFDV', '潜在消费用户', '潜在消费用户', 28, '2025-06-26 09:12:22', '2025-06-28 11:02:00');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for crowd_tags_detail
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `crowd_tags_detail`;
|
||||
CREATE TABLE `crowd_tags_detail` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '人群ID',
|
||||
`user_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户ID',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_tag_user`(`tag_id` ASC, `user_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '人群标签明细' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of crowd_tags_detail
|
||||
-- ----------------------------
|
||||
INSERT INTO `crowd_tags_detail` VALUES (20, 'RQ_KJHKL98UU78H66554GFDV', 'zy123', '2025-06-28 10:53:23', '2025-06-28 10:53:23');
|
||||
INSERT INTO `crowd_tags_detail` VALUES (21, 'RQ_KJHKL98UU78H66554GFDV', 'smile', '2025-06-28 10:53:23', '2025-06-28 10:53:23');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for crowd_tags_job
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `crowd_tags_job`;
|
||||
CREATE TABLE `crowd_tags_job` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '标签ID',
|
||||
`batch_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '批次ID',
|
||||
`tag_type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '标签类型(参与量、消费金额)',
|
||||
`tag_rule` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '标签规则(限定类型 N次)',
|
||||
`stat_start_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计数据,开始时间',
|
||||
`stat_end_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计数据,结束时间',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态;0初始、1计划(进入执行阶段)、2重置、3完成',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_batch_id`(`batch_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '人群标签任务' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of crowd_tags_job
|
||||
-- ----------------------------
|
||||
INSERT INTO `crowd_tags_job` VALUES (1, 'RQ_KJHKL98UU78H66554GFDV', '10001', 0, '100', '2025-06-26 09:13:31', '2025-06-26 09:13:31', 0, '2025-06-26 09:13:31', '2025-06-26 09:13:31');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for group_buy_activity
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `group_buy_activity`;
|
||||
CREATE TABLE `group_buy_activity` (
|
||||
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增',
|
||||
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||
`activity_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '活动名称',
|
||||
`discount_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '折扣ID',
|
||||
`group_type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '拼团方式(0自动成团、1达成目标拼团)',
|
||||
`take_limit_count` int NOT NULL DEFAULT 1 COMMENT '拼团次数限制',
|
||||
`target` int NOT NULL DEFAULT 1 COMMENT '拼团目标',
|
||||
`valid_time` int NOT NULL DEFAULT 15 COMMENT '拼团时长(分钟)',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '活动状态(0创建、1生效、2过期、3废弃)',
|
||||
`start_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '活动开始时间',
|
||||
`end_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '活动结束时间',
|
||||
`tag_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '人群标签规则标识',
|
||||
`tag_scope` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '人群标签规则范围(多选;1可见限制、2参与限制)',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_activity_id`(`activity_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '拼团活动' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of group_buy_activity
|
||||
-- ----------------------------
|
||||
INSERT INTO `group_buy_activity` VALUES (1, 100123, '测试活动', '25120207', 0, 1, 3, 60, 1, '2025-06-19 10:19:40', '2025-07-31 10:19:40', 'RQ_KJHKL98UU78H66554GFDV', '1,2', '2025-06-19 10:19:40', '2025-07-03 18:25:55');
|
||||
INSERT INTO `group_buy_activity` VALUES (2, 100124, '测试活动2', '25120207', 0, 1, 1, 60, 1, '2025-07-05 13:39:52', '2025-09-28 13:39:34', 'RQ_KJHKL98UU78H66554GFDV', '1,2', '2025-07-05 13:39:52', '2025-07-05 13:40:06');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for group_buy_discount
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `group_buy_discount`;
|
||||
CREATE TABLE `group_buy_discount` (
|
||||
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`discount_id` int NOT NULL COMMENT '折扣ID',
|
||||
`discount_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '折扣标题',
|
||||
`discount_desc` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '折扣描述',
|
||||
`discount_type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '折扣类型(0:base、1:tag)',
|
||||
`market_plan` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'ZJ' COMMENT '营销优惠计划(ZJ:直减、MJ:满减、ZK:折扣、N元购)',
|
||||
`market_expr` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '营销优惠表达式',
|
||||
`tag_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '人群标签,特定优惠限定',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_discount_id`(`discount_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '折扣配置' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of group_buy_discount
|
||||
-- ----------------------------
|
||||
INSERT INTO `group_buy_discount` VALUES (1, 25120207, '直减优惠20元', '直减优惠20元', 0, 'ZJ', '20', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||
INSERT INTO `group_buy_discount` VALUES (2, 25120208, '满减优惠100-10元', '满减优惠100-10元', 0, 'MJ', '100,10', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||
INSERT INTO `group_buy_discount` VALUES (4, 25120209, '折扣优惠8折', '折扣优惠8折', 0, 'ZK', '0.8', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||
INSERT INTO `group_buy_discount` VALUES (5, 25120210, 'N元购买优惠', 'N元购买优惠', 0, 'N', '1.99', NULL, '2025-06-25 14:02:13', '2025-06-25 14:02:13');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for group_buy_order
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `group_buy_order`;
|
||||
CREATE TABLE `group_buy_order` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`team_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '拼单组队ID',
|
||||
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||
`original_price` decimal(8, 2) NOT NULL COMMENT '原始价格',
|
||||
`deduction_price` decimal(8, 2) NOT NULL COMMENT '折扣金额',
|
||||
`pay_price` decimal(8, 2) NOT NULL COMMENT '支付价格',
|
||||
`target_count` int NOT NULL COMMENT '目标数量',
|
||||
`complete_count` int NOT NULL COMMENT '完成数量',
|
||||
`lock_count` int NOT NULL COMMENT '锁单数量',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态(0-拼单中、1-完成、2-失败)',
|
||||
`valid_start_time` datetime NOT NULL COMMENT '拼团开始时间',
|
||||
`valid_end_time` datetime NOT NULL COMMENT '拼团结束时间',
|
||||
`notify_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'HTTP' COMMENT '回调类型(HTTP、MQ)',
|
||||
`notify_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '回调地址(HTTP 回调不可为空)',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_team_id`(`team_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '拼团订单表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of group_buy_order
|
||||
-- ----------------------------
|
||||
INSERT INTO `group_buy_order` VALUES (39, '92219797', 100124, 's01', 'c01', 100.00, 20.00, 80.00, 1, 1, 1, 1, '2025-07-19 18:08:18', '2025-07-19 19:08:18', 'MQ', NULL, '2025-07-19 18:08:18', '2025-07-19 18:08:55');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for group_buy_order_list
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `group_buy_order_list`;
|
||||
CREATE TABLE `group_buy_order_list` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户ID',
|
||||
`team_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '拼单组队ID',
|
||||
`order_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '订单ID',
|
||||
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||
`start_time` datetime NOT NULL COMMENT '活动开始时间',
|
||||
`end_time` datetime NOT NULL COMMENT '活动结束时间',
|
||||
`goods_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品ID',
|
||||
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||
`original_price` decimal(8, 2) NOT NULL COMMENT '原始价格',
|
||||
`deduction_price` decimal(8, 2) NOT NULL COMMENT '折扣金额',
|
||||
`pay_price` decimal(8, 2) NOT NULL COMMENT '支付金额',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态;0初始锁定、1消费完成',
|
||||
`out_trade_no` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '外部交易单号-确保外部调用唯一幂等',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`biz_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '业务唯一ID',
|
||||
`out_trade_time` datetime NULL DEFAULT NULL COMMENT '外部交易时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_order_id`(`order_id` ASC) USING BTREE,
|
||||
INDEX `idx_user_id_activity_id`(`user_id` ASC, `activity_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 35 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '拼团订单明细表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of group_buy_order_list
|
||||
-- ----------------------------
|
||||
INSERT INTO `group_buy_order_list` VALUES (37, 'smile02', '92219797', '527461199182', 100124, '2025-07-05 13:39:52', '2025-09-28 13:39:34', '9890001', 's01', 'c01', 100.00, 20.00, 80.00, 1, '334152190173', '2025-07-19 18:08:18', '2025-07-19 18:08:55', '100124_smile02_1', '2025-07-19 18:08:55');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for notify_task
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `notify_task`;
|
||||
CREATE TABLE `notify_task` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||
`team_id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '拼单组队ID',
|
||||
`notify_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'HTTP' COMMENT '回调类型(HTTP、MQ)',
|
||||
`notify_mq` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '回调消息',
|
||||
`notify_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '回调接口',
|
||||
`notify_count` int NOT NULL COMMENT '回调次数',
|
||||
`notify_status` tinyint(1) NOT NULL COMMENT '回调状态【0初始、1完成、2重试、3失败】',
|
||||
`parameter_json` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '参数对象',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_team_id`(`team_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of notify_task
|
||||
-- ----------------------------
|
||||
INSERT INTO `notify_task` VALUES (7, 100124, '92219797', 'MQ', 'topic.team_success', NULL, 1, 1, '{\"teamId\":\"92219797\",\"outTradeNoList\":[\"334152190173\"]}', '2025-07-19 18:08:55', '2025-07-19 18:08:55');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sc_sku_activity
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sc_sku_activity`;
|
||||
CREATE TABLE `sc_sku_activity` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||
`activity_id` bigint NOT NULL COMMENT '活动ID',
|
||||
`goods_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品ID',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_sc_goodsid`(`source` ASC, `channel` ASC, `goods_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '渠道商品活动配置关联表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sc_sku_activity
|
||||
-- ----------------------------
|
||||
INSERT INTO `sc_sku_activity` VALUES (1, 's01', 'c01', 100123, '9890001', '2025-06-26 17:15:54', '2025-06-26 17:15:54');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sku
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sku`;
|
||||
CREATE TABLE `sku` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`source` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '渠道',
|
||||
`channel` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '来源',
|
||||
`goods_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品ID',
|
||||
`goods_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称',
|
||||
`original_price` decimal(10, 2) NOT NULL COMMENT '商品价格',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uq_goods_id`(`goods_id` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '商品信息' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sku
|
||||
-- ----------------------------
|
||||
INSERT INTO `sku` VALUES (1, 's01', 'c01', '9890001', '《手写MyBatis:渐进式源码实践》', 100.00, '2025-06-22 11:10:06', '2025-06-22 11:10:06');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
@ -13,6 +13,16 @@
|
||||
|
||||
Date: 16/07/2025 17:09:09
|
||||
*/
|
||||
-- 如果存在就删除
|
||||
DROP DATABASE IF EXISTS `group_buying_sys`;
|
||||
|
||||
-- 创建(如需指定字符集与排序规则,可自行调整)
|
||||
CREATE DATABASE IF NOT EXISTS `group_buying_sys`
|
||||
DEFAULT CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- 切换到该库
|
||||
USE `group_buying_sys`;
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
@ -22,7 +22,39 @@ public class LockMarketPayOrderRequestDTO {
|
||||
private String channel;
|
||||
// 外部交易单号
|
||||
private String outTradeNo;
|
||||
// 回调地址
|
||||
// 回调配置,调用方自己配置回调类型
|
||||
private NotifyConfigVO notifyConfigVO;
|
||||
|
||||
// 兼容旧配置,用户仍可继续使用setNotifyUrl方法
|
||||
public void setNotifyUrl(String url) {
|
||||
NotifyConfigVO notifyConfigVO = new NotifyConfigVO();
|
||||
notifyConfigVO.setNotifyType("HTTP");
|
||||
notifyConfigVO.setNotifyUrl(url);
|
||||
this.notifyConfigVO = notifyConfigVO;
|
||||
}
|
||||
|
||||
// 兼容配置 - MQ不需要指定,系统会发统一MQ消息
|
||||
public void setNotifyMQ() {
|
||||
NotifyConfigVO notifyConfigVO = new NotifyConfigVO();
|
||||
notifyConfigVO.setNotifyType("MQ");
|
||||
this.notifyConfigVO = notifyConfigVO;
|
||||
}
|
||||
|
||||
// 回调配置
|
||||
@Data
|
||||
public static class NotifyConfigVO {
|
||||
/**
|
||||
* 回调方式;MQ、HTTP
|
||||
*/
|
||||
private String notifyType;
|
||||
/**
|
||||
* 回调消息
|
||||
*/
|
||||
private String notifyMQ;
|
||||
/**
|
||||
* 回调地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,8 +3,9 @@ package edu.whut.config;
|
||||
import org.springframework.amqp.core.*;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
//@Configuration
|
||||
@Configuration
|
||||
public class RabbitMQConfig {
|
||||
|
||||
@Value("${spring.rabbitmq.config.producer.exchange}")
|
||||
|
@ -17,6 +17,7 @@
|
||||
<result column="status" property="status"/>
|
||||
<result column="valid_start_time" property="validStartTime"/>
|
||||
<result column="valid_end_time" property="validEndTime"/>
|
||||
<result column="notify_type" property="notifyType"/>
|
||||
<result column="notify_url" property="notifyUrl"/>
|
||||
<result column="create_time" property="createTime"/>
|
||||
<result column="update_time" property="updateTime"/>
|
||||
@ -26,10 +27,10 @@
|
||||
insert into group_buy_order(
|
||||
team_id, activity_id, source, channel, original_price,
|
||||
deduction_price, pay_price, target_count, complete_count,
|
||||
lock_count, status, valid_start_time, valid_end_time, notify_url, create_time, update_time
|
||||
lock_count, status, valid_start_time, valid_end_time, notify_type, notify_url, create_time, update_time
|
||||
) values(
|
||||
#{teamId}, #{activityId}, #{source}, #{channel}, #{originalPrice},
|
||||
#{deductionPrice}, #{payPrice}, #{targetCount}, #{completeCount}, #{lockCount}, 0, #{validStartTime}, #{validEndTime} ,#{notifyUrl},now(), now()
|
||||
#{deductionPrice}, #{payPrice}, #{targetCount}, #{completeCount}, #{lockCount}, 0, #{validStartTime}, #{validEndTime},#{notifyType}, #{notifyUrl},now(), now()
|
||||
)
|
||||
</insert>
|
||||
|
||||
@ -67,13 +68,14 @@
|
||||
</select>
|
||||
|
||||
<select id="queryGroupBuyTeamByTeamId" parameterType="java.lang.String" resultMap="dataMap">
|
||||
select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,notify_url
|
||||
select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,
|
||||
notify_type, notify_url
|
||||
from group_buy_order where team_id = #{teamId}
|
||||
</select>
|
||||
|
||||
<select id="queryGroupBuyProgressByTeamIds" parameterType="java.util.Set" resultMap="dataMap">
|
||||
select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,
|
||||
notify_url
|
||||
notify_type, notify_url
|
||||
from group_buy_order
|
||||
where status = 0 and target_count > lock_count and valid_end_time > now() and team_id in
|
||||
<foreach item="teamId" collection="teamIds" open="(" separator="," close=")">
|
||||
|
@ -6,6 +6,8 @@
|
||||
<id column="id" property="id"/>
|
||||
<result column="activity_id" property="activityId"/>
|
||||
<result column="team_id" property="teamId"/>
|
||||
<result column="notify_type" property="notifyType"/>
|
||||
<result column="notify_mq" property="notifyMQ"/>
|
||||
<result column="notify_url" property="notifyUrl"/>
|
||||
<result column="notify_count" property="notifyCount"/>
|
||||
<result column="notify_status" property="notifyStatus"/>
|
||||
@ -15,20 +17,21 @@
|
||||
</resultMap>
|
||||
|
||||
<insert id="insert" parameterType="edu.whut.infrastructure.dao.po.NotifyTask">
|
||||
insert into notify_task(activity_id, team_id, notify_url, notify_count, notify_status, parameter_json,
|
||||
insert into notify_task(
|
||||
activity_id, team_id, notify_type, notify_mq, notify_url, notify_count, notify_status, parameter_json,
|
||||
create_time, update_time)
|
||||
values(#{activityId}, #{teamId}, #{notifyUrl}, #{notifyCount}, #{notifyStatus}, #{parameterJson}, now(),now())
|
||||
values(#{activityId}, #{teamId}, #{notifyType}, #{notifyMQ}, #{notifyUrl}, #{notifyCount}, #{notifyStatus}, #{parameterJson}, now(),now())
|
||||
</insert>
|
||||
|
||||
<select id="queryUnExecutedNotifyTaskList" resultMap="dataMap">
|
||||
select activity_id, team_id, notify_url, notify_count, notify_status, parameter_json
|
||||
select activity_id, team_id, notify_type, notify_mq, notify_url, notify_count, notify_status, parameter_json
|
||||
from notify_task
|
||||
where notify_status in (0, 2)
|
||||
limit 50
|
||||
</select>
|
||||
|
||||
<select id="queryUnExecutedNotifyTaskByTeamId" resultMap="dataMap">
|
||||
select activity_id, team_id, notify_url, notify_count, notify_status, parameter_json
|
||||
select activity_id, team_id, notify_type, notify_mq, notify_url, notify_count, notify_status, parameter_json
|
||||
from notify_task
|
||||
where team_id = #{teamId} and notify_status in (0, 2)
|
||||
</select>
|
||||
|
@ -12,6 +12,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* 拼团交易结算服务测试
|
||||
@ -34,12 +35,15 @@ public class TradeSettlementOrderServiceTest {
|
||||
TradePaySuccessEntity tradePaySuccessEntity = new TradePaySuccessEntity();
|
||||
tradePaySuccessEntity.setSource("s01");
|
||||
tradePaySuccessEntity.setChannel("c01");
|
||||
tradePaySuccessEntity.setUserId("zy01");
|
||||
tradePaySuccessEntity.setOutTradeNo("451247062978");
|
||||
tradePaySuccessEntity.setUserId("smile02");
|
||||
tradePaySuccessEntity.setOutTradeNo("334152190173");
|
||||
tradePaySuccessEntity.setOutTradeTime(new Date()); //交易时间
|
||||
TradePaySettlementEntity tradePaySettlementEntity = tradeSettlementOrderService.settlementMarketPayOrder(tradePaySuccessEntity);
|
||||
log.info("请求参数:{}", JSON.toJSONString(tradePaySuccessEntity));
|
||||
log.info("测试结果:{}", JSON.toJSONString(tradePaySettlementEntity));
|
||||
|
||||
// 暂停,等待MQ消息。处理完后,手动关闭程序
|
||||
new CountDownLatch(1).await();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,22 @@ public class MarketTradeControllerTest {
|
||||
@Resource
|
||||
private IMarketTradeService marketTradeService;
|
||||
|
||||
@Test
|
||||
public void test_lockMarketPayOrder_mq() throws InterruptedException {
|
||||
LockMarketPayOrderRequestDTO lockMarketPayOrderRequestDTO = new LockMarketPayOrderRequestDTO();
|
||||
lockMarketPayOrderRequestDTO.setUserId("smile02");
|
||||
lockMarketPayOrderRequestDTO.setTeamId(null);
|
||||
lockMarketPayOrderRequestDTO.setActivityId(100124L);
|
||||
lockMarketPayOrderRequestDTO.setGoodsId("9890001");
|
||||
lockMarketPayOrderRequestDTO.setSource("s01");
|
||||
lockMarketPayOrderRequestDTO.setChannel("c01");
|
||||
lockMarketPayOrderRequestDTO.setNotifyMQ();
|
||||
lockMarketPayOrderRequestDTO.setOutTradeNo(RandomStringUtils.randomNumeric(12));
|
||||
|
||||
Response<LockMarketPayOrderResponseDTO> lockMarketPayOrderResponseDTOResponse = marketTradeService.lockMarketPayOrder(lockMarketPayOrderRequestDTO);
|
||||
|
||||
log.info("测试结果 req:{} res:{}", JSON.toJSONString(lockMarketPayOrderRequestDTO), JSON.toJSONString(lockMarketPayOrderResponseDTOResponse));
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟第一个用户创建拼团
|
||||
|
@ -27,7 +27,7 @@ public interface ITradeRepository {
|
||||
|
||||
GroupBuyTeamEntity queryGroupBuyTeamByTeamId(String teamId);
|
||||
|
||||
boolean settlementMarketPayOrder(GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate);
|
||||
NotifyTaskEntity settlementMarketPayOrder(GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate);
|
||||
|
||||
boolean isSCBlackIntercept(String source, String channel);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
package edu.whut.domain.trade.model.entity;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyConfigVO;
|
||||
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@ -32,7 +33,7 @@ public class GroupBuyTeamEntity {
|
||||
private Date validStartTime;
|
||||
/** 拼团结束时间 - 拼团有效时长 */
|
||||
private Date validEndTime;
|
||||
/** 回调地址 */
|
||||
private String notifyUrl;
|
||||
/** 回调配置 */
|
||||
private NotifyConfigVO notifyConfigVO;
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,14 @@ public class NotifyTaskEntity {
|
||||
* 拼单组队ID
|
||||
*/
|
||||
private String teamId;
|
||||
/**
|
||||
* 回调类型
|
||||
*/
|
||||
private String notifyType;
|
||||
/**
|
||||
* 回调消息
|
||||
*/
|
||||
private String notifyMQ;
|
||||
/**
|
||||
* 回调接口
|
||||
*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
package edu.whut.domain.trade.model.entity;
|
||||
|
||||
import edu.whut.domain.trade.model.valobj.NotifyConfigVO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -32,6 +33,7 @@ public class PayDiscountEntity {
|
||||
private BigDecimal payPrice;
|
||||
/** 外部交易单号-确保外部调用唯一幂等 */
|
||||
private String outTradeNo;
|
||||
/** 回调地址 */
|
||||
private String notifyUrl;
|
||||
/** 回调配置 */
|
||||
private NotifyConfigVO notifyConfigVO;
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
package edu.whut.domain.trade.model.entity;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyConfigVO;
|
||||
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@ -32,7 +33,7 @@ public class TradeSettlementRuleFilterBackEntity {
|
||||
private Date validStartTime;
|
||||
/** 拼团结束时间 - 拼团有效时长 */
|
||||
private Date validEndTime;
|
||||
/** 回调地址 */
|
||||
private String notifyUrl;
|
||||
/** 回调配置 */
|
||||
private NotifyConfigVO notifyConfigVO;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package edu.whut.domain.trade.model.valobj;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 回调配置值对象
|
||||
*/
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class NotifyConfigVO {
|
||||
|
||||
/**
|
||||
* 回调方式;MQ、HTTP
|
||||
*/
|
||||
private NotifyTypeEnumVO notifyType;
|
||||
/**
|
||||
* 回调消息
|
||||
*/
|
||||
private String notifyMQ;
|
||||
/**
|
||||
* 回调地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package edu.whut.domain.trade.model.valobj;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 回调方式枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public enum NotifyTypeEnumVO {
|
||||
|
||||
HTTP("HTTP", "HTTP 回调"),
|
||||
MQ("MQ", "MQ 消息通知"),
|
||||
;
|
||||
|
||||
private String code;
|
||||
private String info;
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package edu.whut.domain.trade.service;
|
||||
|
||||
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
||||
import edu.whut.domain.trade.model.entity.TradePaySettlementEntity;
|
||||
import edu.whut.domain.trade.model.entity.TradePaySuccessEntity;
|
||||
|
||||
@ -34,5 +35,15 @@ public interface ITradeSettlementOrderService {
|
||||
*/
|
||||
Map<String, Integer> execSettlementNotifyJob(String teamId) throws Exception;
|
||||
|
||||
/**
|
||||
* 执行结算通知任务
|
||||
*
|
||||
* @param notifyTaskEntity 通知任务对象
|
||||
* @return 结算数量
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
Map<String, Integer> execSettlementNotifyJob(NotifyTaskEntity notifyTaskEntity) throws Exception;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,14 +8,17 @@ import edu.whut.domain.trade.service.ITradeSettlementOrderService;
|
||||
import edu.whut.domain.trade.service.settlement.factory.TradeSettlementRuleFilterFactory;
|
||||
import edu.whut.types.design.framework.link.model2.chain.BusinessLinkedList;
|
||||
import edu.whut.types.enums.NotifyTaskHTTPEnumVO;
|
||||
import edu.whut.types.exception.AppException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 拼团交易结算服务
|
||||
@ -28,6 +31,8 @@ public class TradeSettlementOrderService implements ITradeSettlementOrderService
|
||||
|
||||
private final ITradePort port;
|
||||
|
||||
private final ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
private final BusinessLinkedList<TradeSettlementRuleCommandEntity, TradeSettlementRuleFilterFactory.DynamicContext, TradeSettlementRuleFilterBackEntity> tradeSettlementRuleFilter;
|
||||
|
||||
|
||||
@ -56,14 +61,21 @@ public class TradeSettlementOrderService implements ITradeSettlementOrderService
|
||||
.tradePaySuccessEntity(tradePaySuccessEntity)
|
||||
.build();
|
||||
|
||||
// 4. 更新数据库,拼团交易结算
|
||||
boolean isNotify =repository.settlementMarketPayOrder(groupBuyTeamSettlementAggregate);
|
||||
// 4. 更新数据库,拼团交易结算,若达到拼团人数,返回notifyTaskEntity发送回调通知,否则返回null不做处理
|
||||
NotifyTaskEntity notifyTaskEntity =repository.settlementMarketPayOrder(groupBuyTeamSettlementAggregate);
|
||||
|
||||
// 5. isNotify为true-> 付款人数达到target,即拼团成功,执行回调任务
|
||||
// 处理失败也会有定时任务补偿,通过这样的方式,可以减轻任务调度,提高时效性
|
||||
if (isNotify) {
|
||||
Map<String, Integer> notifyResultMap = execSettlementNotifyJob(teamId);
|
||||
log.info("回调通知 拼团成功 result:{}", JSON.toJSONString(notifyResultMap));
|
||||
// 5. 组队回调处理 - 处理失败也会有定时任务补偿,通过这样的方式,可以减轻任务调度,提高时效性
|
||||
if (null != notifyTaskEntity) {
|
||||
threadPoolExecutor.execute(() -> {
|
||||
Map<String, Integer> notifyResultMap = null;
|
||||
try {
|
||||
notifyResultMap = execSettlementNotifyJob(notifyTaskEntity);
|
||||
log.info("回调通知拼团完结 result:{}", JSON.toJSONString(notifyResultMap));
|
||||
} catch (Exception e) {
|
||||
log.error("回调通知拼团完结失败 result:{}", JSON.toJSONString(notifyResultMap), e);
|
||||
throw new AppException(e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 6. 返回结算信息 - 公司中开发这样的流程时候,会根据外部需要进行值的设置
|
||||
@ -100,6 +112,12 @@ public class TradeSettlementOrderService implements ITradeSettlementOrderService
|
||||
return execSettlementNotifyJob(notifyTaskEntityList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> execSettlementNotifyJob(NotifyTaskEntity notifyTaskEntity) throws Exception {
|
||||
log.info("拼团交易-执行结算通知回调,指定 teamId:{} notifyTaskEntity:{}", notifyTaskEntity.getTeamId(), JSON.toJSONString(notifyTaskEntity));
|
||||
return execSettlementNotifyJob(Collections.singletonList(notifyTaskEntity));
|
||||
}
|
||||
|
||||
/**
|
||||
*公共逻辑抽取:遍历任务列表,调用外部服务,更新数据库并计数
|
||||
* @param notifyTaskEntityList 待处理的通知任务列表
|
||||
|
@ -1,6 +1,8 @@
|
||||
package edu.whut.infrastructure.adapter.port;
|
||||
import edu.whut.domain.trade.adapter.port.ITradePort;
|
||||
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyTypeEnumVO;
|
||||
import edu.whut.infrastructure.event.EventPublisher;
|
||||
import edu.whut.infrastructure.gateway.GroupBuyNotifyService;
|
||||
import edu.whut.infrastructure.redis.IRedisService;
|
||||
import edu.whut.types.enums.NotifyTaskHTTPEnumVO;
|
||||
@ -20,6 +22,8 @@ public class TradePort implements ITradePort {
|
||||
|
||||
private final IRedisService redisService;
|
||||
|
||||
private final EventPublisher publisher;
|
||||
|
||||
@Override
|
||||
public String groupBuyNotify(NotifyTaskEntity notifyTask) throws Exception {
|
||||
RLock lock = redisService.getLock(notifyTask.lockKey());
|
||||
@ -28,11 +32,20 @@ public class TradePort implements ITradePort {
|
||||
// tryLock(long waitTime, long leaseTime, TimeUnit unit) 最大等待时间,锁自动释放时间(传0表示需手动释放)
|
||||
if (lock.tryLock(3, 0, TimeUnit.SECONDS)) {
|
||||
try {
|
||||
// 回调方式 HTTP
|
||||
if (NotifyTypeEnumVO.HTTP.getCode().equals(notifyTask.getNotifyType())) {
|
||||
// 无效的 notifyUrl 则直接返回成功
|
||||
if (StringUtils.isBlank(notifyTask.getNotifyUrl()) || "暂无".equals(notifyTask.getNotifyUrl())) {
|
||||
return NotifyTaskHTTPEnumVO.SUCCESS.getCode();
|
||||
}
|
||||
return groupBuyNotifyService.groupBuyNotify(notifyTask.getNotifyUrl(), notifyTask.getParameterJson());
|
||||
}
|
||||
|
||||
// 回调方式 MQ
|
||||
if (NotifyTypeEnumVO.MQ.getCode().equals(notifyTask.getNotifyType())) {
|
||||
publisher.publish(notifyTask.getNotifyMQ(), notifyTask.getParameterJson());
|
||||
return NotifyTaskHTTPEnumVO.SUCCESS.getCode();
|
||||
}
|
||||
} finally {
|
||||
//解锁
|
||||
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
|
@ -6,6 +6,8 @@ import edu.whut.domain.trade.model.aggregate.GroupBuyOrderAggregate;
|
||||
import edu.whut.domain.trade.model.aggregate.GroupBuyTeamSettlementAggregate;
|
||||
import edu.whut.domain.trade.model.entity.*;
|
||||
import edu.whut.domain.trade.model.valobj.GroupBuyProgressVO;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyConfigVO;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyTypeEnumVO;
|
||||
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
||||
import edu.whut.infrastructure.dao.IGroupBuyActivityDao;
|
||||
import edu.whut.infrastructure.dao.IGroupBuyOrderDao;
|
||||
@ -26,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -53,6 +56,9 @@ public class TradeRepository implements ITradeRepository {
|
||||
|
||||
private final DCCService dccService;
|
||||
|
||||
@Value("${spring.rabbitmq.config.producer.topic_team_success.routing_key}")
|
||||
private String topic_team_success;
|
||||
|
||||
/**
|
||||
* 根据外部交易号 & 用户id 查询未支付的锁单记录(用于幂等)
|
||||
*/
|
||||
@ -93,6 +99,7 @@ public class TradeRepository implements ITradeRepository {
|
||||
UserEntity user = agg.getUserEntity();
|
||||
PayActivityEntity activity = agg.getPayActivityEntity();
|
||||
PayDiscountEntity discount = agg.getPayDiscountEntity();
|
||||
NotifyConfigVO notifyConfigVO = discount.getNotifyConfigVO();
|
||||
Integer userTakeOrderCount = agg.getUserTakeOrderCount();
|
||||
|
||||
|
||||
@ -122,7 +129,8 @@ public class TradeRepository implements ITradeRepository {
|
||||
.lockCount(1) // 首单已锁定
|
||||
.validStartTime(currentDate)
|
||||
.validEndTime(calendar.getTime())
|
||||
.notifyUrl(discount.getNotifyUrl())
|
||||
.notifyType(notifyConfigVO.getNotifyType().getCode())
|
||||
.notifyUrl(notifyConfigVO.getNotifyUrl())
|
||||
.build();
|
||||
|
||||
groupBuyOrderDao.insert(orderPo);
|
||||
@ -222,10 +230,22 @@ public class TradeRepository implements ITradeRepository {
|
||||
@Override
|
||||
public GroupBuyTeamEntity queryGroupBuyTeamByTeamId(String teamId) {
|
||||
GroupBuyOrder groupBuyOrder = groupBuyOrderDao.queryGroupBuyTeamByTeamId(teamId);
|
||||
GroupBuyTeamEntity groupBuyTeamEntity = new GroupBuyTeamEntity();
|
||||
BeanUtils.copyProperties(groupBuyOrder, groupBuyTeamEntity, "status");
|
||||
groupBuyTeamEntity.setStatus(GroupBuyOrderStatusEnumVO.valueOf(groupBuyOrder.getStatus()));
|
||||
return groupBuyTeamEntity;
|
||||
return GroupBuyTeamEntity.builder()
|
||||
.teamId(groupBuyOrder.getTeamId())
|
||||
.activityId(groupBuyOrder.getActivityId())
|
||||
.targetCount(groupBuyOrder.getTargetCount())
|
||||
.completeCount(groupBuyOrder.getCompleteCount())
|
||||
.lockCount(groupBuyOrder.getLockCount())
|
||||
.status(GroupBuyOrderStatusEnumVO.valueOf(groupBuyOrder.getStatus()))
|
||||
.validStartTime(groupBuyOrder.getValidStartTime())
|
||||
.validEndTime(groupBuyOrder.getValidEndTime())
|
||||
.notifyConfigVO(NotifyConfigVO.builder()
|
||||
.notifyType(NotifyTypeEnumVO.valueOf(groupBuyOrder.getNotifyType()))
|
||||
.notifyUrl(groupBuyOrder.getNotifyUrl())
|
||||
// MQ 是固定的
|
||||
.notifyMQ(topic_team_success)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@ -239,11 +259,12 @@ public class TradeRepository implements ITradeRepository {
|
||||
*/
|
||||
@Transactional(timeout = 500)
|
||||
@Override
|
||||
public boolean settlementMarketPayOrder(GroupBuyTeamSettlementAggregate agg) {
|
||||
public NotifyTaskEntity settlementMarketPayOrder(GroupBuyTeamSettlementAggregate agg) {
|
||||
|
||||
// ========= 1. 聚合拆分 =========
|
||||
UserEntity user = agg.getUserEntity();
|
||||
GroupBuyTeamEntity team = agg.getGroupBuyTeamEntity();
|
||||
NotifyConfigVO notifyConfigVO = team.getNotifyConfigVO();
|
||||
TradePaySuccessEntity payOK = agg.getTradePaySuccessEntity();
|
||||
|
||||
// ========= 2. 更新拼团订单明细状态 =========
|
||||
@ -278,7 +299,9 @@ public class TradeRepository implements ITradeRepository {
|
||||
NotifyTask task = new NotifyTask();
|
||||
task.setActivityId(team.getActivityId());
|
||||
task.setTeamId(team.getTeamId());
|
||||
task.setNotifyUrl(team.getNotifyUrl());
|
||||
task.setNotifyType(notifyConfigVO.getNotifyType().getCode());
|
||||
task.setNotifyMQ(NotifyTypeEnumVO.MQ.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyMQ() : null);
|
||||
task.setNotifyUrl(NotifyTypeEnumVO.HTTP.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyUrl() : null);
|
||||
task.setNotifyCount(0);
|
||||
task.setNotifyStatus(0);
|
||||
task.setParameterJson(JSON.toJSONString(new HashMap<String, Object>() {{
|
||||
@ -287,9 +310,16 @@ public class TradeRepository implements ITradeRepository {
|
||||
}}));
|
||||
|
||||
notifyTaskDao.insert(task);
|
||||
return true;
|
||||
return NotifyTaskEntity.builder()
|
||||
.teamId(task.getTeamId())
|
||||
.notifyType(task.getNotifyType())
|
||||
.notifyMQ(task.getNotifyMQ())
|
||||
.notifyUrl(task.getNotifyUrl())
|
||||
.notifyCount(task.getNotifyCount())
|
||||
.parameterJson(task.getParameterJson())
|
||||
.build();
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -337,6 +367,8 @@ public class TradeRepository implements ITradeRepository {
|
||||
if (null == notifyTask) return new ArrayList<>();
|
||||
return Collections.singletonList(NotifyTaskEntity.builder()
|
||||
.teamId(notifyTask.getTeamId())
|
||||
.notifyType(notifyTask.getNotifyType())
|
||||
.notifyMQ(notifyTask.getNotifyMQ())
|
||||
.notifyUrl(notifyTask.getNotifyUrl())
|
||||
.notifyCount(notifyTask.getNotifyCount())
|
||||
.parameterJson(notifyTask.getParameterJson())
|
||||
|
@ -45,7 +45,9 @@ public class GroupBuyOrder {
|
||||
private Date validStartTime;
|
||||
/** 拼团结束时间 - 拼团有效时长 */
|
||||
private Date validEndTime;
|
||||
/** 回调通知地址 */
|
||||
/** 回调类型 HTTP、MQ */
|
||||
private String notifyType;
|
||||
/** 回调通知(HTTP 方式回调,地址不可为空) */
|
||||
private String notifyUrl;
|
||||
/** 创建时间 */
|
||||
private Date createTime;
|
||||
|
@ -21,6 +21,10 @@ public class NotifyTask {
|
||||
private Long activityId;
|
||||
/** 拼单组队ID */
|
||||
private String teamId;
|
||||
/** 回调类型 */
|
||||
private String notifyType;
|
||||
/** 回调消息 */
|
||||
private String notifyMQ;
|
||||
/** 回调接口 */
|
||||
private String notifyUrl;
|
||||
/** 回调次数 */
|
||||
|
@ -13,6 +13,8 @@ import edu.whut.domain.activity.model.valobj.GroupBuyActivityDiscountVO;
|
||||
import edu.whut.domain.activity.service.IIndexGroupBuyMarketService;
|
||||
import edu.whut.domain.trade.model.entity.*;
|
||||
import edu.whut.domain.trade.model.valobj.GroupBuyProgressVO;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyConfigVO;
|
||||
import edu.whut.domain.trade.model.valobj.NotifyTypeEnumVO;
|
||||
import edu.whut.domain.trade.service.ITradeLockOrderService;
|
||||
import edu.whut.domain.trade.service.ITradeSettlementOrderService;
|
||||
import edu.whut.types.enums.ResponseCode;
|
||||
@ -69,18 +71,25 @@ public class MarketTradeController implements IMarketTradeService {
|
||||
Long activityId = lockMarketPayOrderRequestDTO.getActivityId();
|
||||
String outTradeNo = lockMarketPayOrderRequestDTO.getOutTradeNo();
|
||||
String teamId = lockMarketPayOrderRequestDTO.getTeamId(); //可为空,对应参与拼团or创建拼团
|
||||
String notifyUrl = lockMarketPayOrderRequestDTO.getNotifyUrl();
|
||||
LockMarketPayOrderRequestDTO.NotifyConfigVO notifyConfigVO = lockMarketPayOrderRequestDTO.getNotifyConfigVO();
|
||||
|
||||
log.info("营销锁单开始执行:拼团交易锁单入参 userId={} req={}", userId, JSON.toJSONString(lockMarketPayOrderRequestDTO));
|
||||
|
||||
// 空值校验(任何一个关键字段为空则直接返回错误)
|
||||
if (StringUtils.isAnyBlank(userId, source, channel, goodsId, notifyUrl) || activityId == null) {
|
||||
boolean httpWithoutUrl =
|
||||
"HTTP".equals(notifyConfigVO.getNotifyType())
|
||||
&& StringUtils.isBlank(notifyConfigVO.getNotifyUrl());
|
||||
|
||||
if (StringUtils.isAnyBlank(userId, source, channel, goodsId)
|
||||
|| activityId == null
|
||||
|| httpWithoutUrl) {
|
||||
return Response.<LockMarketPayOrderResponseDTO>builder()
|
||||
.code(ResponseCode.ILLEGAL_PARAMETER.getCode())
|
||||
.info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
/* ---------- 2. 查询是否已存在未支付锁单 ---------- */
|
||||
MarketPayOrderEntity marketPayOrderEntity =
|
||||
tradeOrderService.queryNoPayMarketPayOrderByOutTradeNo(userId, outTradeNo);
|
||||
@ -147,7 +156,13 @@ public class MarketTradeController implements IMarketTradeService {
|
||||
.deductionPrice(trialBalance.getDeductionPrice())
|
||||
.payPrice(trialBalance.getPayPrice())
|
||||
.outTradeNo(outTradeNo)
|
||||
.notifyUrl(notifyUrl)
|
||||
.notifyConfigVO(
|
||||
// 构建回调通知对象
|
||||
NotifyConfigVO.builder()
|
||||
.notifyType(NotifyTypeEnumVO.valueOf(notifyConfigVO.getNotifyType()))
|
||||
.notifyMQ(notifyConfigVO.getNotifyMQ())
|
||||
.notifyUrl(notifyConfigVO.getNotifyUrl())
|
||||
.build())
|
||||
.build());
|
||||
|
||||
log.info("交易锁单成功 userId={} order={}", userId, JSON.toJSONString(marketPayOrderEntity));
|
||||
|
Loading…
x
Reference in New Issue
Block a user