diff --git a/group-common/src/main/java/com/group/common/domin/pojo/KillOrderEntity.java b/group-common/src/main/java/com/group/common/domin/pojo/KillOrderEntity.java
index a4f5d77..3695ff6 100644
--- a/group-common/src/main/java/com/group/common/domin/pojo/KillOrderEntity.java
+++ b/group-common/src/main/java/com/group/common/domin/pojo/KillOrderEntity.java
@@ -3,14 +3,17 @@ package com.group.common.domin.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Builder;
import lombok.Data;
+import java.math.BigDecimal;
import java.util.Date;
/**
* 秒杀订单表
*/
@Data
+@Builder
@TableName("t_kill_order")
public class KillOrderEntity {
/**
@@ -38,5 +41,9 @@ public class KillOrderEntity {
* 秒杀订单创建时间
*/
private Date orderCreate ;
+ /**
+ * 秒杀商品价格
+ */
+ private BigDecimal killPrice;
}
diff --git a/group-common/src/main/java/com/group/common/domin/pojo/PayDetail.java b/group-common/src/main/java/com/group/common/domin/pojo/PayDetail.java
index b19ea0f..660b6d3 100644
--- a/group-common/src/main/java/com/group/common/domin/pojo/PayDetail.java
+++ b/group-common/src/main/java/com/group/common/domin/pojo/PayDetail.java
@@ -1,5 +1,6 @@
package com.group.common.domin.pojo;
+import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -17,38 +18,44 @@ import java.util.Date;
@Builder
public class PayDetail {
/**
- *
+ * 订单详情主键
*/
- @TableId
- private Integer payId ;
+ @TableId(type = IdType.AUTO)
+ private Integer payId;
/**
* 订单支付金额
*/
- @TableField("pay_title")
- private BigDecimal payTitle ;
+ @TableField("pay_price")
+ private BigDecimal payPrice;
/**
* 订单id
*/
@TableField("pay_order")
- private Integer payOrder ;
+ private Integer payOrder;
/**
* 支付宝编号
*/
@TableField("pay_pay")
- private String payPay ;
+ private String payPay;
/**
- * 明细状态 1-待支付 2-已支付 3-支付失败
+ * 明细状态 1-待支付 2-支付成功 3-支付失败
*/
@TableField("pay_state")
- private Integer payState ;
+ private Integer payState;
/**
* 创建时间
*/
@TableField("pay_create")
- private Date payCreate ;
+ private Date payCreate;
/**
* 支付时间
*/
@TableField("pay_payed")
- private Date payPayed ;
+ private String payPayed;
+ /**
+ * 订单支付流水编号
+ */
+ @TableField("pay_detail")
+ private String payDetail;
+
}
diff --git a/group-module/group_goods/pom.xml b/group-module/group_goods/pom.xml
index df181ae..1e1bb3e 100644
--- a/group-module/group_goods/pom.xml
+++ b/group-module/group_goods/pom.xml
@@ -23,5 +23,10 @@
com.song
group-common
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
\ No newline at end of file
diff --git a/group-module/group_goods/src/main/java/com/group/goods/config/RabbitAdminConfig.java b/group-module/group_goods/src/main/java/com/group/goods/config/RabbitAdminConfig.java
new file mode 100644
index 0000000..4eae44c
--- /dev/null
+++ b/group-module/group_goods/src/main/java/com/group/goods/config/RabbitAdminConfig.java
@@ -0,0 +1,49 @@
+package com.group.goods.config;
+
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class RabbitAdminConfig {
+
+ @Value("${spring.rabbitmq.host}")
+ private String host;
+ @Value("${spring.rabbitmq.username}")
+ private String username;
+ @Value("${spring.rabbitmq.password}")
+ private String password;
+ @Value("${spring.rabbitmq.virtualhost}")
+ private String virtualhost;
+
+ /**
+ * 构建RabbitMQ的连接工厂
+ * @return
+ */
+ @Bean
+ public ConnectionFactory connectionFactory() {
+ CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
+ connectionFactory.setAddresses(host);
+ connectionFactory.setUsername(username);
+ connectionFactory.setPassword(password);
+ connectionFactory.setVirtualHost(virtualhost);
+ return connectionFactory;
+ }
+
+
+ /**
+ * 初始化RabbitAdmin
+ * @param connectionFactory
+ * @return
+ */
+ @Bean
+ public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
+ RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
+ rabbitAdmin.setAutoStartup(true);
+ return rabbitAdmin;
+ }
+
+}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/config/RabbitMQConfig.java b/group-module/group_goods/src/main/java/com/group/goods/config/RabbitMQConfig.java
new file mode 100644
index 0000000..9e36708
--- /dev/null
+++ b/group-module/group_goods/src/main/java/com/group/goods/config/RabbitMQConfig.java
@@ -0,0 +1,86 @@
+package com.group.goods.config;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+
+@Configuration
+public class RabbitMQConfig implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback{
+
+ public static final String QUEUE = "order_queue";
+ public static final String EXCHANGE = "order_exchange";
+ public static final String ROUTINGKEY = "order_routing_key";
+
+
+
+ public static final Logger logger = LoggerFactory.getLogger(RabbitMQConfig.class);
+
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+
+ //创建消息转换器
+ @Bean
+ public MessageConverter messageConverter(){
+ return new Jackson2JsonMessageConverter();
+ }
+
+
+
+ @Bean
+ public Queue queue(){
+ return new Queue(QUEUE,true);
+ }
+
+ @Bean
+ public DirectExchange directExchange(){
+
+ return new DirectExchange(EXCHANGE);
+
+ }
+
+ @Bean
+ public Binding binding(){
+ return BindingBuilder.bind(queue()).to(directExchange()).with(ROUTINGKEY);
+ }
+
+
+ @PostConstruct
+ public void rabbitTemplate(){
+
+ rabbitTemplate.setConfirmCallback(this);
+ rabbitTemplate.setReturnsCallback(this);
+ }
+
+
+
+
+ @Override
+ public void confirm(CorrelationData correlationData, boolean ack, String s) {
+
+ if (ack){
+ logger.info("{}消息到达交换机",correlationData.getId());
+ }else {
+ logger.info("{}消息丢失", correlationData.getId());
+ }
+
+ }
+
+ @Override
+ public void returnedMessage(ReturnedMessage returnedMessage) {
+
+ logger.error("{}消息未到达队列",returnedMessage.getMessage().getMessageProperties().getMessageId());
+
+ }
+}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/config/RedissonConfig.java b/group-module/group_goods/src/main/java/com/group/goods/config/RedissonConfig.java
new file mode 100644
index 0000000..c9bfa4a
--- /dev/null
+++ b/group-module/group_goods/src/main/java/com/group/goods/config/RedissonConfig.java
@@ -0,0 +1,31 @@
+package com.group.goods.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.codec.JsonJacksonCodec;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+/**
+ * redisson配置
+ */
+@Component
+public class RedissonConfig {
+
+ @Value("${spring.redis.host}")
+ private String host;
+
+ @Value("${spring.redis.port}")
+ private String post;
+
+ @Bean
+ public RedissonClient redissonClient(){
+ Config config = new Config();
+ config.useSingleServer().setAddress(host+post);
+ config.setCodec(new JsonJacksonCodec());
+ return Redisson.create(config);
+ }
+}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/controller/SecKillController.java b/group-module/group_goods/src/main/java/com/group/goods/controller/SecKillController.java
index 1e490e9..82de701 100644
--- a/group-module/group_goods/src/main/java/com/group/goods/controller/SecKillController.java
+++ b/group-module/group_goods/src/main/java/com/group/goods/controller/SecKillController.java
@@ -19,18 +19,11 @@ public class SecKillController {
private SecKillService secKillService;
/**
- * 秒杀商品 - 采用最简单方式进行实现
+ * 秒杀商品 - 采用最简单方式进行实现 -使用了redisson框架
*/
@GetMapping("/buyGoodsByOne/{id}")
public R buyGoodsByOne(@PathVariable("id")Integer id){
return secKillService.buyGoodsByOne(id);
}
- /**
- * 秒杀方式 -- 采用降低锁粒度的方式实现
- */
-
- /**
- * 秒杀商品 -- 采用redisson信号量的方式进行解决这个问题
- */
}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/feign/KillOrderService.java b/group-module/group_goods/src/main/java/com/group/goods/feign/KillOrderService.java
index 2a859e1..7c5a866 100644
--- a/group-module/group_goods/src/main/java/com/group/goods/feign/KillOrderService.java
+++ b/group-module/group_goods/src/main/java/com/group/goods/feign/KillOrderService.java
@@ -1,7 +1,11 @@
package com.group.goods.feign;
+import com.group.common.domin.pojo.KillOrderEntity;
+import com.group.common.result.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
@@ -11,5 +15,11 @@ import org.springframework.web.bind.annotation.RequestParam;
public interface KillOrderService {
@GetMapping("/killOrder/exitResult")
- public boolean exitResult(@RequestParam Integer goodsId, Integer userId);
+ public boolean exitResult(@RequestParam Integer goodsId,@RequestParam Integer userId);
+
+ @PostMapping("/killOrder/addOrder")
+ public R addOrder(@RequestBody KillOrderEntity killOrderEntity);
+
+ @PostMapping ("/deleteOrder")
+ public void deleteOrder(@RequestBody KillOrderEntity killOrderEntity);
}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/mq/Consumer.java b/group-module/group_goods/src/main/java/com/group/goods/mq/Consumer.java
new file mode 100644
index 0000000..6250969
--- /dev/null
+++ b/group-module/group_goods/src/main/java/com/group/goods/mq/Consumer.java
@@ -0,0 +1,93 @@
+package com.group.goods.mq;
+
+import cn.hutool.core.util.IdUtil;
+import com.alibaba.fastjson.JSON;
+import com.group.common.domin.pojo.KillOrderEntity;
+import com.group.common.domin.pojo.SeckillEntity;
+import com.group.common.redis.RedisCache;
+import com.group.goods.config.RabbitMQConfig;
+import com.group.goods.feign.KillOrderService;
+import com.group.goods.pojo.ReqKill;
+import com.group.goods.service.SecKillService;
+import com.rabbitmq.client.Channel;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 消费者
+ */
+@Log4j2
+@Component
+public class Consumer {
+
+ @Autowired
+ private RedisCache redisCache;
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+ @Autowired
+ private SecKillService secKillService;
+
+ @Autowired
+ private KillOrderService killOrderService;
+
+
+ @RabbitListener(queues = RabbitMQConfig.QUEUE)
+ public void addOrder(Message message, Channel channel) {
+ MessageProperties properties = message.getMessageProperties();
+ String messageId = properties.getMessageId();
+ //判断消息是否重复消费
+ if (redisCache.hasKey(messageId)) {
+ //当这个messageId存在时,证明已经消费过
+ return;
+ }
+ //拿到传送来的消息
+ String o = (String) rabbitTemplate.getMessageConverter().fromMessage(message);
+ ReqKill reqKill = JSON.parseObject(o, ReqKill.class);
+ //执行业务
+ //通过商品id获取对应的实体类
+ SeckillEntity entity = secKillService.getById(reqKill.getGoodsId());
+ //生成秒杀订单编号
+ String killId = IdUtil.getSnowflakeNextId()+"";
+ //生成订单实体类
+ //生成订单 商品id 用户id 当前时间 支付金额 商品编号
+ KillOrderEntity order = KillOrderEntity
+ .builder()
+ .goodsId(reqKill.getGoodsId())
+ .userId(reqKill.getUserId())
+ .killPrice(entity.getSeckillPrice())
+ .killId(killId)
+ .orderCreate(new Date())
+ .build();
+ killOrderService.addOrder(order);
+ //将messageId存入redis缓存中
+ redisCache.setCacheObject(messageId, messageId, 30L, TimeUnit.MINUTES);
+ //手动确认消息
+ try {
+ channel.basicAck(properties.getDeliveryTag(),false);
+ } catch (IOException e) {
+ //当消息消费确认失败
+ //删除添加的订单
+ killOrderService.deleteOrder(order);
+ //将消息重新放回队列中
+ try {
+ channel.basicReject(properties.getDeliveryTag(),true);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ throw new RuntimeException(e);
+ }
+ }
+
+
+}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/mq/Product.java b/group-module/group_goods/src/main/java/com/group/goods/mq/Product.java
new file mode 100644
index 0000000..59d32fc
--- /dev/null
+++ b/group-module/group_goods/src/main/java/com/group/goods/mq/Product.java
@@ -0,0 +1,44 @@
+package com.group.goods.mq;
+
+import cn.hutool.core.util.IdUtil;
+import com.alibaba.fastjson.JSON;
+import com.group.common.redis.RedisCache;
+import com.group.goods.config.RabbitMQConfig;
+import com.group.goods.pojo.ReqKill;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 生产者
+ */
+@Component
+public class Product {
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+
+ /**
+ * mq异步生成订单
+ */
+ public void addOrder(ReqKill reqKill) {
+ long messageId = IdUtil.getSnowflakeNextId();
+ MessageProperties messageProperties = new MessageProperties();
+ messageProperties.setMessageId( messageId+"");
+ //将reqKill放到队列中,等待消费
+ Message message = rabbitTemplate
+ .getMessageConverter()
+ .toMessage(JSON.toJSONString(reqKill)
+ , messageProperties);
+ rabbitTemplate.sendAndReceive(
+ RabbitMQConfig.EXCHANGE,
+ RabbitMQConfig.ROUTINGKEY,
+ message
+ );
+ }
+
+
+}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/pojo/ReqKill.java b/group-module/group_goods/src/main/java/com/group/goods/pojo/ReqKill.java
new file mode 100644
index 0000000..a8affee
--- /dev/null
+++ b/group-module/group_goods/src/main/java/com/group/goods/pojo/ReqKill.java
@@ -0,0 +1,14 @@
+package com.group.goods.pojo;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * mq请求订单生成类
+ */
+@Data
+@Builder
+public class ReqKill {
+ private Integer userId;
+ private Integer goodsId;
+}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/service/SecKillService.java b/group-module/group_goods/src/main/java/com/group/goods/service/SecKillService.java
index 5ea586f..cfbb957 100644
--- a/group-module/group_goods/src/main/java/com/group/goods/service/SecKillService.java
+++ b/group-module/group_goods/src/main/java/com/group/goods/service/SecKillService.java
@@ -9,4 +9,5 @@ import com.group.common.result.R;
*/
public interface SecKillService extends IService {
R buyGoodsByOne(Integer id);
+
}
diff --git a/group-module/group_goods/src/main/java/com/group/goods/service/impl/SecKillServiceImpl.java b/group-module/group_goods/src/main/java/com/group/goods/service/impl/SecKillServiceImpl.java
index 0efcb38..4596f8b 100644
--- a/group-module/group_goods/src/main/java/com/group/goods/service/impl/SecKillServiceImpl.java
+++ b/group-module/group_goods/src/main/java/com/group/goods/service/impl/SecKillServiceImpl.java
@@ -1,7 +1,6 @@
package com.group.goods.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.group.common.domin.pojo.KillOrderEntity;
import com.group.common.domin.pojo.SessionEntity;
import com.group.common.redis.RedisCache;
import com.group.common.result.R;
@@ -9,10 +8,12 @@ import com.group.common.util.UserUtil;
import com.group.goods.feign.KillOrderService;
import com.group.goods.mapper.SecKillMapper;
import com.group.common.domin.pojo.SeckillEntity;
+import com.group.goods.mq.Product;
+import com.group.goods.pojo.ReqKill;
import com.group.goods.service.SecKillService;
import com.group.goods.service.SessionService;
-import org.redisson.Redisson;
import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
@@ -43,7 +44,10 @@ public class SecKillServiceImpl extends ServiceImplcom.song
group-common
+
+
+
+ com.alipay.sdk
+ alipay-sdk-java
+ 4.35.79.ALL
+
+
+
+ com.alipay.sdk
+ alipay-easysdk
+ 2.2.0
+
\ No newline at end of file
diff --git a/group-module/group_order/src/main/java/com/group/order/config/AliPayConfig.java b/group-module/group_order/src/main/java/com/group/order/config/AliPayConfig.java
new file mode 100644
index 0000000..234fe46
--- /dev/null
+++ b/group-module/group_order/src/main/java/com/group/order/config/AliPayConfig.java
@@ -0,0 +1,40 @@
+package com.group.order.config;
+
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component
+@Data
+@ConfigurationProperties(prefix = "alipay")
+public class AliPayConfig {
+
+ // 支付宝的AppId
+ private String appId;
+ // 应用私钥
+ private String appPrivateKey;
+ // 支付宝公钥
+ private String alipayPublicKey;
+ // 支付宝通知本地的接口完整地址
+ private String notifyUrl;
+ //支付宝跳转的地址
+ private String gatewayUrl ;
+ private String format;
+ private String charset;
+ //签名方式
+ private String signType;
+ //回调本地地址
+ private String returnUrl;
+
+ private String productCode;
+
+ @Bean
+ public AlipayClient alipayClient(){
+ return new DefaultAlipayClient(gatewayUrl,appId,appPrivateKey,format,charset,alipayPublicKey,signType);
+ }
+
+
+}
diff --git a/group-module/group_order/src/main/java/com/group/order/config/CorsConfig.java b/group-module/group_order/src/main/java/com/group/order/config/CorsConfig.java
new file mode 100644
index 0000000..e768f4c
--- /dev/null
+++ b/group-module/group_order/src/main/java/com/group/order/config/CorsConfig.java
@@ -0,0 +1,25 @@
+package com.group.order.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 跨域配置
+ */
+@Configuration
+public class CorsConfig {
+
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
+ corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
+ corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
+ source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
+ return new CorsFilter(source);
+ }
+}
\ No newline at end of file
diff --git a/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java b/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java
index a21c464..0e9caff 100644
--- a/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java
+++ b/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java
@@ -1,16 +1,22 @@
package com.group.order.controller;
+import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.group.common.domin.pojo.KillOrderEntity;
import com.group.common.domin.pojo.PayDetail;
import com.group.common.result.R;
-import com.group.order.payMethod.PayContext;
-import com.group.order.payMethod.PayType;
+import com.group.order.config.AliPayConfig;
import com.group.order.pojo.ReqPay;
import com.group.order.service.KillOrderService;
+import com.group.order.service.PayDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* 秒杀订单控制层
*/
@@ -27,33 +33,90 @@ public class KillOrderController {
* 如果为true,证明该用户已经购买过该商品
*/
@GetMapping("/exitResult")
- public boolean exitResult(@RequestParam Integer goodsId,Integer userId){
+ public boolean exitResult(@RequestParam Integer goodsId, @RequestParam Integer userId) {
KillOrderEntity one = killOrderService.getOne(new LambdaQueryWrapper()
.eq(KillOrderEntity::getGoodsId, goodsId)
.eq(KillOrderEntity::getUserId, userId));
return one != null;
}
+ /**
+ * 生成秒杀订单
+ */
+ @PostMapping("/addOrder")
+ public R addOrder(@RequestBody KillOrderEntity killOrderEntity) {
+ if (killOrderService.save(killOrderEntity)) {
+ return R.error();
+ }
+ return R.ok();
+ }
+
+ /**
+ * 删除生成的订单
+ */
+ @PostMapping("/deleteOrder")
+ public void deleteOrder(@RequestBody KillOrderEntity killOrderEntity) {
+ killOrderService.removeById(killOrderEntity);
+ }
/**
* 支付秒杀订单
*/
@PostMapping("/payKill")
- public R payKill(@RequestBody ReqPay pay){
- return killOrderService.payKill(pay);
+ public R payKill(@RequestBody ReqPay pay, HttpServletResponse response) {
+ return killOrderService.payKill(pay, response);
}
@Autowired
- private PayContext payContext;
+ private AliPayConfig aliPayConfig;
+
+ @Autowired
+ private PayDetailService payDetailService;
/**
- * 测试支付模式
+ * 支付宝回调
*/
- @GetMapping("/test")
- public R test(@RequestParam Integer type){
-// PayType pay = payContext.getPay(type);
-// pay.pay(PayDetail.builder().build());
- return R.ok("支付成功");
+ @PostMapping("/notify") // 注意这里必须是POST接口
+ public void payNotify(HttpServletRequest request) throws Exception {
+ System.out.println("支付宝触发回调");
+ if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
+ System.out.println("=========支付宝异步回调========");
+ Map params = new HashMap<>();
+ Map requestParams = request.getParameterMap();
+ for (String name : requestParams.keySet()) {
+ params.put(name, request.getParameter(name));
+ }
+ String sign = params.get("sign");
+ String content = AlipaySignature.getSignCheckContentV1(params);
+ boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8"); // 验证签名
+ // 支付宝验签
+ if (checkSignature) {
+ // 验签通过
+ System.out.println("交易名称: " + params.get("subject"));
+ System.out.println("交易状态: " + params.get("trade_status"));
+ System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
+ System.out.println("商户订单号: " + params.get("out_trade_no"));
+ System.out.println("交易金额: " + params.get("total_amount"));
+ System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
+ System.out.println("买家付款时间: " + params.get("gmt_payment"));
+ System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
+ String tradeNo = params.get("out_trade_no"); // 订单编号
+ String gmtPayment = params.get("gmt_payment"); // 支付时间
+ String alipayTradeNo = params.get("trade_no"); // 支付宝交易编号
+ // 更新订单状态为已支付,设置支付信息
+ PayDetail pay = payDetailService
+ .getOne(new LambdaQueryWrapper()
+ .eq(PayDetail::getPayDetail, tradeNo));
+ pay.setPayPayed(gmtPayment);
+ pay.setPayState(2);
+ pay.setPayPay(alipayTradeNo);
+ payDetailService.updateById(pay);
+ }
+ }
}
+
+
+
+
}
diff --git a/group-module/group_order/src/main/java/com/group/order/payMethod/AliPay.java b/group-module/group_order/src/main/java/com/group/order/payMethod/AliPay.java
index 3f4dbbc..bd86d2c 100644
--- a/group-module/group_order/src/main/java/com/group/order/payMethod/AliPay.java
+++ b/group-module/group_order/src/main/java/com/group/order/payMethod/AliPay.java
@@ -1,15 +1,49 @@
package com.group.order.payMethod;
+import cn.hutool.json.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.request.AlipayTradePagePayRequest;
import com.group.common.domin.pojo.PayDetail;
+import com.group.order.config.AliPayConfig;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
/**
* 支付宝支付
*/
@Component
public class AliPay implements PayType {
+
+ @Autowired
+ private AlipayClient alipayClient;
+
+ @Autowired
+ private AliPayConfig aliPayConfig;
+
+
@Override
- public void pay(PayDetail payDetail) {
+ public void pay(PayDetail payDetail, HttpServletResponse response) {
+ AlipayTradePagePayRequest request = getAlipayTradePagePayRequest(payDetail);
+ // 执行请求,拿到响应的结果,返回给浏览器
+ String form = "";
+ try {
+ form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ }
+ response.setContentType("text/html;charset=" + aliPayConfig.getCharset());
+ try {
+ response.getWriter().write(form);// 直接将完整的表单html输出到页面
+ response.getWriter().flush();
+ response.getWriter().close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
System.out.println("支付宝支付");
}
@@ -17,4 +51,17 @@ public class AliPay implements PayType {
public String getName() {
return PayEnum.BYALI.getName();
}
+
+ private AlipayTradePagePayRequest getAlipayTradePagePayRequest(PayDetail payDetail) {
+ AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
+ request.setNotifyUrl(aliPayConfig.getNotifyUrl());
+ JSONObject bizContent = new JSONObject();
+ bizContent.set("out_trade_no", payDetail.getPayDetail()); // 订单详情的编号
+ bizContent.set("total_amount",payDetail.getPayPrice()); // 订单的总金额
+ bizContent.set("subject", payDetail.getPayOrder()); // 支付的名称
+ bizContent.set("product_code", aliPayConfig.getProductCode());
+ request.setBizContent(bizContent.toString());
+ request.setReturnUrl(aliPayConfig.getReturnUrl());// 支付完成后自动跳转到本地页面的路径
+ return request;
+ }
}
diff --git a/group-module/group_order/src/main/java/com/group/order/payMethod/CardPay.java b/group-module/group_order/src/main/java/com/group/order/payMethod/CardPay.java
index 4d931ab..6967910 100644
--- a/group-module/group_order/src/main/java/com/group/order/payMethod/CardPay.java
+++ b/group-module/group_order/src/main/java/com/group/order/payMethod/CardPay.java
@@ -3,13 +3,15 @@ package com.group.order.payMethod;
import com.group.common.domin.pojo.PayDetail;
import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletResponse;
+
/**
* 银行卡支付
*/
@Component
public class CardPay implements PayType{
@Override
- public void pay(PayDetail payDetail) {
+ public void pay(PayDetail payDetail, HttpServletResponse response) {
System.out.println("银行卡支付");
}
diff --git a/group-module/group_order/src/main/java/com/group/order/payMethod/PayContext.java b/group-module/group_order/src/main/java/com/group/order/payMethod/PayContext.java
index 40932a2..8d33f94 100644
--- a/group-module/group_order/src/main/java/com/group/order/payMethod/PayContext.java
+++ b/group-module/group_order/src/main/java/com/group/order/payMethod/PayContext.java
@@ -35,6 +35,7 @@ public class PayContext implements InitializingBean, ApplicationContextAware {
*/
public PayType getPay(Integer type){
String payType=null;
+
if (type==1){
payType=PayEnum.BYALI.getName();
}
diff --git a/group-module/group_order/src/main/java/com/group/order/payMethod/PayType.java b/group-module/group_order/src/main/java/com/group/order/payMethod/PayType.java
index 8a9fe09..5fa942e 100644
--- a/group-module/group_order/src/main/java/com/group/order/payMethod/PayType.java
+++ b/group-module/group_order/src/main/java/com/group/order/payMethod/PayType.java
@@ -3,12 +3,14 @@ package com.group.order.payMethod;
import com.group.common.domin.pojo.PayDetail;
import com.group.common.result.R;
+import javax.servlet.http.HttpServletResponse;
+
/**
* 抽象接口
*/
public interface PayType {
- public void pay(PayDetail payDetail);
+ public void pay(PayDetail payDetail,HttpServletResponse response);
public String getName();
}
diff --git a/group-module/group_order/src/main/java/com/group/order/payMethod/WeChat.java b/group-module/group_order/src/main/java/com/group/order/payMethod/WeChat.java
index 6cf39c5..d31e2e4 100644
--- a/group-module/group_order/src/main/java/com/group/order/payMethod/WeChat.java
+++ b/group-module/group_order/src/main/java/com/group/order/payMethod/WeChat.java
@@ -3,13 +3,15 @@ package com.group.order.payMethod;
import com.group.common.domin.pojo.PayDetail;
import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletResponse;
+
/**
*微信支付
*/
@Component
public class WeChat implements PayType{
@Override
- public void pay(PayDetail payDetail) {
+ public void pay(PayDetail payDetail, HttpServletResponse response) {
System.out.println("微信支付");
}
diff --git a/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java b/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java
index 4a6c103..3952b5a 100644
--- a/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java
+++ b/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java
@@ -5,9 +5,11 @@ import com.group.common.domin.pojo.KillOrderEntity;
import com.group.common.result.R;
import com.group.order.pojo.ReqPay;
+import javax.servlet.http.HttpServletResponse;
+
/**
* 秒杀订单服务层
*/
public interface KillOrderService extends IService {
- R payKill(ReqPay pay);
+ R payKill(ReqPay pay, HttpServletResponse response);
}
diff --git a/group-module/group_order/src/main/java/com/group/order/service/PayDetailService.java b/group-module/group_order/src/main/java/com/group/order/service/PayDetailService.java
new file mode 100644
index 0000000..0b87d59
--- /dev/null
+++ b/group-module/group_order/src/main/java/com/group/order/service/PayDetailService.java
@@ -0,0 +1,10 @@
+package com.group.order.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.group.common.domin.pojo.PayDetail;
+
+/**
+ * 订单支付详情业务层
+ */
+public interface PayDetailService extends IService {
+}
diff --git a/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java b/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java
index dac40f3..6e6f896 100644
--- a/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java
+++ b/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java
@@ -12,10 +12,14 @@ import com.group.order.payMethod.PayContext;
import com.group.order.payMethod.PayType;
import com.group.order.pojo.ReqPay;
import com.group.order.service.KillOrderService;
+import com.group.order.service.PayDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import javax.servlet.http.HttpServletResponse;
import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* 秒杀订单实现层
@@ -24,35 +28,49 @@ import java.util.Date;
public class KillOrderServiceImpl extends ServiceImpl
implements KillOrderService {
- @Autowired
- private PayDetailMapper payDetailMapper;
@Autowired
private PayContext payContext;
+ @Autowired
+ private PayDetailService payDetailService;
+
@Override
- public R payKill(ReqPay pay) {
+ public R payKill(ReqPay pay, HttpServletResponse response) {
//安全校验
- //防止幂等性
+ //防止幂等性,避免已经成功或者失败的订单重新支付
KillOrderEntity order = getById(pay.getOrderId());
- if (order.getKillState()!=1){
+ if (order.getKillState()==2){
return R.error("订单已经支付,请不要重复支付");
}
+ if (order.getKillState()==3){
+ return R.error("订单已经过期,请重新下单");
+ }
+ //判断是否有支付流水正在处理中
+ List details = payDetailService
+ .list()
+ .stream()
+ .filter(c -> c.getPayOrder().equals(pay.getOrderId()))
+ .collect(Collectors.toList());
+ if (!details.isEmpty()){
+ PayDetail detail = details.get(details.size() - 1);
+ if (detail.getPayState()==1){
+ return R.error("订单正在支付中,请不要重复支付");
+ }
+ if (detail.getPayState()==2){
+ return R.error("该订单已经支付成功,请不要重复支付");
+ }
+ }
//生成详细支付订单
PayDetail payDetail = PayDetail.builder()
- .payPay(IdUtil.getSnowflakeNextIdStr())
+ .payDetail(IdUtil.getSnowflakeNextIdStr())
.payOrder(pay.getOrderId())
.payCreate(new Date())
- .payTitle(pay.getPrice())
+ .payPrice(pay.getPrice())
.build();
- payDetailMapper.insert(payDetail);
- PayType pay1 = payContext.getPay(pay.getType());
- pay1.pay(payDetail);
-
-
-
-
-
- return null;
+ payDetailService.save(payDetail);
+ PayType type = payContext.getPay(pay.getType());
+ type.pay(payDetail,response);
+ return R.ok();
}
}
diff --git a/group-module/group_order/src/main/java/com/group/order/service/impl/PayDetailServiceImpl.java b/group-module/group_order/src/main/java/com/group/order/service/impl/PayDetailServiceImpl.java
new file mode 100644
index 0000000..87417e0
--- /dev/null
+++ b/group-module/group_order/src/main/java/com/group/order/service/impl/PayDetailServiceImpl.java
@@ -0,0 +1,16 @@
+package com.group.order.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.group.common.domin.pojo.PayDetail;
+import com.group.order.mapper.PayDetailMapper;
+import com.group.order.service.PayDetailService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 订单支付详情实现层
+ */
+@Service
+public class PayDetailServiceImpl extends ServiceImpl
+ implements PayDetailService {
+
+}