diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 6931629..059632e 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -13,6 +13,7 @@
+
@@ -26,6 +27,7 @@
+
@@ -44,6 +46,8 @@
+
+
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 3afc4a8..d60ad9c 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -9,6 +9,7 @@
+
@@ -20,6 +21,7 @@
+
diff --git a/atguigu-tuan/common/http.api.js b/atguigu-tuan/common/http.api.js
index 965ed62..050c8f7 100644
--- a/atguigu-tuan/common/http.api.js
+++ b/atguigu-tuan/common/http.api.js
@@ -24,7 +24,7 @@ const post_submit_order = '/order/auth/submitOrder' // 生成订单
const get_order_info = '/order/auth/getOrderInfoById' // 订单详情
const get_wx_login = '/user/weixin/wxLogin' // 微信用户登陆
const post_update_user = '/user/weixin/auth/updateUser' // 更新用户信息
-const get_weixin_payment = '/payment/weixin/createJsapi/' // 获取微信支付信息
+const get_weixin_payment = '/payment/weixin/createJsapi' // 获取微信支付信息
const get_find_user_order = '/order/auth/findUserOrderPage' // 获取用户订单信息
const get_order_status = '/payment/weixin/queryPayStatus' // 获取订单状态
diff --git a/atguigu-tuan/unpackage/dist/dev/mp-weixin/common/vendor.js b/atguigu-tuan/unpackage/dist/dev/mp-weixin/common/vendor.js
index aa9b9a6..74a915d 100644
--- a/atguigu-tuan/unpackage/dist/dev/mp-weixin/common/vendor.js
+++ b/atguigu-tuan/unpackage/dist/dev/mp-weixin/common/vendor.js
@@ -25932,7 +25932,7 @@
var get_order_info = '/order/auth/getOrderInfoById'; // 订单详情
var get_wx_login = '/user/weixin/wxLogin'; // 微信用户登陆
var post_update_user = '/user/weixin/auth/updateUser'; // 更新用户信息
- var get_weixin_payment = '/payment/weixin/createJsapi/'; // 获取微信支付信息
+ var get_weixin_payment = '/payment/weixin/createJsapi'; // 获取微信支付信息
var get_find_user_order = '/order/auth/findUserOrderPage'; // 获取用户订单信息
var get_order_status = '/payment/weixin/queryPayStatus'; // 获取订单状态
diff --git a/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/Result.java b/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/Result.java
index 255f02c..8d31ed5 100644
--- a/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/Result.java
+++ b/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/Result.java
@@ -26,7 +26,7 @@ public class Result {
//设置数据,返回对象的方法
public static Result build(T data, Integer code, String message) {
- //创建Result对象,设置值,返回对象
+ //创建Resullt对象,设置值,返回对象
Result result = new Result<>();
//判断返回结果中是否需要数据
if (data != null) {
@@ -40,9 +40,10 @@ public class Result {
return result;
}
+
//设置数据,返回对象的方法
public static Result build(T data, ResultCodeEnum resultCodeEnum) {
- //创建Result对象,设置值,返回对象
+ //创建Resullt对象,设置值,返回对象
Result result = new Result<>();
//判断返回结果中是否需要数据
if (data != null) {
@@ -58,11 +59,13 @@ public class Result {
//成功的方法
public static Result ok(T data) {
- return build(data, ResultCodeEnum.SUCCESS);
+ Result result = build(data, ResultCodeEnum.SUCCESS);
+ return result;
}
//失败的方法
public static Result fail(T data) {
return build(data, ResultCodeEnum.FAIL);
}
+
}
diff --git a/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/ResultCodeEnum.java b/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/ResultCodeEnum.java
index 9d852c8..b99243e 100644
--- a/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/ResultCodeEnum.java
+++ b/guigu-ssyx-parent/common/service-util/src/main/java/com/atguigu/ssyx/common/result/ResultCodeEnum.java
@@ -13,18 +13,36 @@ import lombok.Getter;
@Getter
public enum ResultCodeEnum {
- SUCCESS(200, "成功"), FAIL(201, "失败"), SERVICE_ERROR(2012, "服务异常"), DATA_ERROR(204, "数据异常"), ILLEGAL_REQUEST(205, "非法请求"), REPEAT_SUBMIT(206, "重复提交"),
+ SUCCESS(200, "成功"),
+ FAIL(201, "失败"),
- LOGIN_AUTH(208, "未登陆"), PERMISSION(209, "没有权限"),
+ SERVICE_ERROR(2012, "服务异常"),
+ DATA_ERROR(204, "数据异常"),
+ ILLEGAL_REQUEST(205, "非法请求"),
+ REPEAT_SUBMIT(206, "重复提交"),
- ORDER_PRICE_ERROR(210, "订单商品价格变化"), ORDER_STOCK_FALL(204, "订单库存锁定失败"), CREATE_ORDER_FAIL(210, "创建订单失败"),
+ LOGIN_AUTH(208, "未登陆"),
+ PERMISSION(209, "没有权限"),
- COUPON_GET(220, "优惠券已经领取"), COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
+ ORDER_PRICE_ERROR(210, "订单商品价格变化"),
+ ORDER_STOCK_FALL(204, "订单库存锁定失败"),
+ CREATE_ORDER_FAIL(210, "创建订单失败"),
- URL_ENCODE_ERROR(216, "URL编码失败"), ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"), FETCH_ACCESSTOKEN_FAILD(218, "获取accessToken失败"), FETCH_USERINFO_ERROR(219, "获取用户信息失败"),
+ COUPON_GET(220, "优惠券已经领取"),
+ COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
+
+ URL_ENCODE_ERROR(216, "URL编码失败"),
+ ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"),
+ FETCH_ACCESSTOKEN_FAILD(218, "获取accessToken失败"),
+ FETCH_USERINFO_ERROR(219, "获取用户信息失败"),
- SKU_LIMIT_ERROR(230, "购买个数不能大于限购个数"), REGION_OPEN(240, "该区域已开通"), REGION_NO_OPEN(240, "该区域未开通"),
+ SKU_LIMIT_ERROR(230, "购买个数不能大于限购个数"),
+ REGION_OPEN(240, "该区域已开通"),
+ REGION_NO_OPEN(240, "该区域未开通"),
+ PAYMENT_WAITING(242, "订单支付中"),
+ PAYMENT_SUCCESS(241, "订单支付成功"),
+ PAYMENT_FAIL(243, "订单支付失败"),
;
private final Integer code;
diff --git a/guigu-ssyx-parent/service-client/pom.xml b/guigu-ssyx-parent/service-client/pom.xml
index 2cf6840..c061650 100644
--- a/guigu-ssyx-parent/service-client/pom.xml
+++ b/guigu-ssyx-parent/service-client/pom.xml
@@ -17,6 +17,7 @@
service-search-client
service-activity-client
service-cart-client
+ service-order-client
diff --git a/guigu-ssyx-parent/service-client/service-order-client/pom.xml b/guigu-ssyx-parent/service-client/service-order-client/pom.xml
new file mode 100644
index 0000000..a58059d
--- /dev/null
+++ b/guigu-ssyx-parent/service-client/service-order-client/pom.xml
@@ -0,0 +1,20 @@
+
+
+ 4.0.0
+
+ com.atguigu
+ service-client
+ 1.0-SNAPSHOT
+
+
+ service-order-client
+
+
+ 8
+ 8
+ UTF-8
+
+
+
diff --git a/guigu-ssyx-parent/service-client/service-order-client/src/main/java/com/atguigu/ssyx/client/order/OrderFeignClient.java b/guigu-ssyx-parent/service-client/service-order-client/src/main/java/com/atguigu/ssyx/client/order/OrderFeignClient.java
new file mode 100644
index 0000000..d43fb2f
--- /dev/null
+++ b/guigu-ssyx-parent/service-client/service-order-client/src/main/java/com/atguigu/ssyx/client/order/OrderFeignClient.java
@@ -0,0 +1,22 @@
+package com.atguigu.ssyx.client.order;
+
+import com.atguigu.ssyx.model.order.OrderInfo;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+/**
+ * ClassName: OrderFeignClient
+ * Package: com.atguigu.ssyx.client.order
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 11:03
+ */
+@FeignClient(value = "service-order")
+public interface OrderFeignClient {
+
+ @ApiOperation(value = "根据orderNo查询订单信息")
+ @GetMapping("/api/order/inner/getOrderInfo/{orderNo}")
+ OrderInfo getOrderInfo(@PathVariable("orderNo") String orderNo);
+}
diff --git a/guigu-ssyx-parent/service/pom.xml b/guigu-ssyx-parent/service/pom.xml
index 9c16709..3b3e859 100644
--- a/guigu-ssyx-parent/service/pom.xml
+++ b/guigu-ssyx-parent/service/pom.xml
@@ -21,6 +21,7 @@
service-home
service-cart
service-order
+ service-payment
diff --git a/guigu-ssyx-parent/service/service-cart/src/main/resources/application-dev.yml b/guigu-ssyx-parent/service/service-cart/src/main/resources/application-dev.yml
index d685efb..bd43581 100644
--- a/guigu-ssyx-parent/service/service-cart/src/main/resources/application-dev.yml
+++ b/guigu-ssyx-parent/service/service-cart/src/main/resources/application-dev.yml
@@ -12,6 +12,11 @@ feign:
spring:
main:
allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
+ rabbitmq:
+ host: 43.143.164.194
+ port: 5672
+ username: guest
+ password: guest
redis:
host: 82.157.68.223
port: 6379
diff --git a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/controller/OrderInfoController.java b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/controller/OrderInfoController.java
index a41b27f..293f687 100644
--- a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/controller/OrderInfoController.java
+++ b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/controller/OrderInfoController.java
@@ -1,12 +1,17 @@
package com.atguigu.ssyx.order.controller;
+import com.atguigu.ssyx.common.auth.AuthContextHolder;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.order.OrderInfo;
import com.atguigu.ssyx.order.service.OrderInfoService;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
import com.atguigu.ssyx.vo.order.OrderSubmitVo;
+import com.atguigu.ssyx.vo.order.OrderUserQueryVo;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -22,10 +27,28 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/api/order")
public class OrderInfoController {
-
@Autowired
private OrderInfoService orderInfoService;
+ @ApiOperation(value = "订单查询")
+ @GetMapping("auth/findUserOrderPage/{page}/{limit}")
+ public Result findUserOrderPage(
+ @ApiParam(name = "page", value = "当前页码", required = true)
+ @PathVariable Long page,
+ @ApiParam(name = "limit", value = "每页记录数", required = true)
+ @PathVariable Long limit,
+ @ApiParam(name = "orderVo", value = "查询对象", required = false)
+ OrderUserQueryVo orderUserQueryVo) {
+ //获取userId
+ Long userId = AuthContextHolder.getUserId();
+ orderUserQueryVo.setUserId(userId);
+
+ //分页查询条件
+ Page pageParam = new Page<>(page, limit);
+ IPage pageModel = orderInfoService.getOrderInfoByUserIdPage(pageParam, orderUserQueryVo);
+ return Result.ok(pageModel);
+ }
+
@ApiOperation("确认订单")
@GetMapping("auth/confirmOrder")
public Result confirm() {
diff --git a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/receiver/OrderReceiver.java b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/receiver/OrderReceiver.java
new file mode 100644
index 0000000..e049321
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/receiver/OrderReceiver.java
@@ -0,0 +1,44 @@
+package com.atguigu.ssyx.order.receiver;
+
+import com.atguigu.ssyx.mq.constant.MqConst;
+import com.atguigu.ssyx.order.service.OrderInfoService;
+import com.rabbitmq.client.Channel;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+
+/**
+ * ClassName: OrderReceiver
+ * Package: com.atguigu.ssyx.order.receiver
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 14:15
+ */
+@Component
+public class OrderReceiver {
+ @Autowired
+ private OrderInfoService orderInfoService;
+
+ //订单支付成功,更新订单状态,扣减库存
+ @RabbitListener(bindings = @QueueBinding(
+ value = @Queue(value = MqConst.QUEUE_ORDER_PAY, durable = "true"),
+ exchange = @Exchange(value = MqConst.EXCHANGE_PAY_DIRECT),
+ key = {MqConst.ROUTING_PAY_SUCCESS}
+ ))
+ public void orderPay(String orderNo,
+ Message message,
+ Channel channel) throws IOException {
+ if (!StringUtils.isEmpty(orderNo)) {
+ orderInfoService.orderPay(orderNo);
+ }
+ channel.basicAck(message.getMessageProperties().getDeliveryTag(),
+ false);
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/OrderInfoService.java b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/OrderInfoService.java
index f84316c..9121965 100644
--- a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/OrderInfoService.java
+++ b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/OrderInfoService.java
@@ -3,6 +3,9 @@ package com.atguigu.ssyx.order.service;
import com.atguigu.ssyx.model.order.OrderInfo;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
import com.atguigu.ssyx.vo.order.OrderSubmitVo;
+import com.atguigu.ssyx.vo.order.OrderUserQueryVo;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
/**
@@ -45,4 +48,20 @@ public interface OrderInfoService extends IService {
* @return
*/
OrderInfo getOrderInfoByOrderNo(String orderNo);
+
+ /**
+ * 订单支付成功,更新订单状态,扣减库存
+ *
+ * @param orderNo
+ */
+ void orderPay(String orderNo);
+
+ /**
+ * 订单查询
+ *
+ * @param pageParam
+ * @param orderUserQueryVo
+ * @return
+ */
+ IPage getOrderInfoByUserIdPage(Page pageParam, OrderUserQueryVo orderUserQueryVo);
}
diff --git a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/impl/OrderInfoServiceImpl.java b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/impl/OrderInfoServiceImpl.java
index 72316f1..5574ab1 100644
--- a/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/impl/OrderInfoServiceImpl.java
+++ b/guigu-ssyx-parent/service/service-order/src/main/java/com/atguigu/ssyx/order/service/impl/OrderInfoServiceImpl.java
@@ -24,9 +24,12 @@ import com.atguigu.ssyx.order.service.OrderItemService;
import com.atguigu.ssyx.vo.order.CartInfoVo;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
import com.atguigu.ssyx.vo.order.OrderSubmitVo;
+import com.atguigu.ssyx.vo.order.OrderUserQueryVo;
import com.atguigu.ssyx.vo.product.SkuStockLockVo;
import com.atguigu.ssyx.vo.user.LeaderAddressVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
@@ -328,7 +331,61 @@ public class OrderInfoServiceImpl extends ServiceImpl().eq(OrderInfo::getOrderNo, orderNo));
+ }
+
+ /**
+ * 订单支付成功,更新订单状态,扣减库存
+ *
+ * @param orderNo
+ */
+ @Override
+ public void orderPay(String orderNo) {
+ //查询订单状态是否已经修改完成了支付状态
+ OrderInfo orderInfo = this.getOrderInfoByOrderNo(orderNo);
+ if (orderInfo == null || orderInfo.getOrderStatus() != OrderStatus.UNPAID) {
+ return;
+ }
+ //更新状态
+ this.updateOrderStatus(orderInfo.getId());
+
+ //扣减库存
+ rabbitService.sendMessage(MqConst.EXCHANGE_ORDER_DIRECT, MqConst.ROUTING_MINUS_STOCK, orderNo);
+ }
+
+ /**
+ * 订单查询
+ *
+ * @param pageParam
+ * @param orderUserQueryVo
+ * @return
+ */
+ @Override
+ public IPage getOrderInfoByUserIdPage(Page pageParam, OrderUserQueryVo orderUserQueryVo) {
+ IPage pageModel = baseMapper.selectPage(pageParam, new LambdaQueryWrapper()
+ .eq(OrderInfo::getUserId, orderUserQueryVo.getUserId())
+ .eq(OrderInfo::getOrderStatus, orderUserQueryVo.getOrderStatus()));
+
+ //获取每个订单,把每个订单里面订单项查询封装
+ List orderInfoList = pageModel.getRecords();
+ for (OrderInfo orderInfo : orderInfoList) {
+ //根据订单id查询里面所有订单项列表
+ List orderItemList = orderItemMapper.selectList(new LambdaQueryWrapper()
+ .eq(OrderItem::getOrderId, orderInfo.getId()));
+ //把订单项集合封装到每个订单里面
+ orderInfo.setOrderItemList(orderItemList);
+ //封装订单状态名称
+ orderInfo.getParam().put("orderStatusName", orderInfo.getOrderStatus().getComment());
+ }
+ return pageModel;
+ }
+
+ //更新状态
+ private void updateOrderStatus(Long id) {
+ OrderInfo orderInfo = baseMapper.selectById(id);
+ orderInfo.setOrderStatus(OrderStatus.WAITING_DELEVER);
+ orderInfo.setProcessStatus(ProcessStatus.WAITING_DELEVER);
+ baseMapper.updateById(orderInfo);
}
//计算总金额
diff --git a/guigu-ssyx-parent/service/service-payment/Dockerfile b/guigu-ssyx-parent/service/service-payment/Dockerfile
new file mode 100644
index 0000000..b04938c
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/Dockerfile
@@ -0,0 +1,5 @@
+FROM openjdk:8-jdk-alpine
+LABEL authors="yovinchen"
+VOLUME /tmp
+ADD ./target/service-payment.jar service-order.jar
+ENTRYPOINT ["java","-jar","/service-payment.jar", "&"]
diff --git a/guigu-ssyx-parent/service/service-payment/pom.xml b/guigu-ssyx-parent/service/service-payment/pom.xml
new file mode 100644
index 0000000..00f322c
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/pom.xml
@@ -0,0 +1,39 @@
+
+
+ 4.0.0
+
+ com.atguigu
+ service
+ 1.0-SNAPSHOT
+
+
+ service-payment
+
+
+
+ com.github.wxpay
+ wxpay-sdk
+ 0.0.3
+
+
+ com.atguigu
+ service-order-client
+ 1.0-SNAPSHOT
+ compile
+
+
+ com.atguigu
+ rabbit_util
+ 1.0-SNAPSHOT
+ compile
+
+
+
+ 8
+ 8
+ UTF-8
+
+
+
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/ServicePaymentApplication.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/ServicePaymentApplication.java
new file mode 100644
index 0000000..2a6b66e
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/ServicePaymentApplication.java
@@ -0,0 +1,22 @@
+package com.atguigu.ssyx;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * ClassName: ServicePaymentApplication
+ * Package: vom.atguigu.ssyx
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:29
+ */
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableFeignClients
+public class ServicePaymentApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ServicePaymentApplication.class, args);
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/controller/WeiXinController.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/controller/WeiXinController.java
new file mode 100644
index 0000000..409908e
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/controller/WeiXinController.java
@@ -0,0 +1,66 @@
+package com.atguigu.ssyx.payment.controller;
+
+import com.atguigu.ssyx.common.result.Result;
+import com.atguigu.ssyx.common.result.ResultCodeEnum;
+import com.atguigu.ssyx.payment.service.PaymentInfoService;
+import com.atguigu.ssyx.payment.service.WeixinService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * ClassName: WeiXinController
+ * Package: com.atguigu.ssyx.payment.controller
+ * 微信支付API
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:32
+ */
+@Api(tags = "微信支付接口")
+@RestController
+@RequestMapping("/api/payment/weixin")
+@Slf4j
+public class WeiXinController {
+
+ @Autowired
+ private WeixinService weixinService;
+
+ @Autowired
+ private PaymentInfoService paymentInfoService;
+
+ @ApiOperation(value = "调用微信支付系统生成预付单")
+ @GetMapping("/createJsapi/{orderNo}")
+ public Result createJsapi(@PathVariable("orderNo") String orderNo) {
+ Map map = weixinService.createJsapi(orderNo);
+ return Result.ok(map);
+ }
+
+ @ApiOperation(value = "查询订单支付状态")
+ @GetMapping("/queryPayStatus/{orderNo}")
+ public Result queryPayStatus(@PathVariable("orderNo") String orderNo) {
+ //1 调用微信支付系统接口查询订单支付状态
+ Map resultMap = weixinService.queryPayStatus(orderNo);
+
+ //2 微信支付系统返回值为null,支付失败
+ if (resultMap == null) {
+ return Result.build(null, ResultCodeEnum.PAYMENT_FAIL);
+ }
+
+ //3 如果微信支付系统返回值,判断支付成功
+ if ("SUCCESS".equals(resultMap.get("trade_state"))) {
+ String out_trade_no = resultMap.get("out_trade_no");
+ paymentInfoService.paySuccess(out_trade_no, resultMap);
+ return Result.ok(null);
+ }
+
+ //4 支付中,等待
+ return Result.build(null, ResultCodeEnum.PAYMENT_WAITING);
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/mapper/PaymentInfoMapper.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/mapper/PaymentInfoMapper.java
new file mode 100644
index 0000000..6706c07
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/mapper/PaymentInfoMapper.java
@@ -0,0 +1,16 @@
+package com.atguigu.ssyx.payment.mapper;
+
+import com.atguigu.ssyx.model.order.PaymentInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * 支付信息表 Mapper 接口
+ *
+ *
+ * @author atguigu
+ * @since 2023-10-12
+ */
+public interface PaymentInfoMapper extends BaseMapper {
+
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/mapper/xml/PaymentInfoMapper.xml b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/mapper/xml/PaymentInfoMapper.xml
new file mode 100644
index 0000000..06b9d25
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/mapper/xml/PaymentInfoMapper.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/PaymentInfoService.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/PaymentInfoService.java
new file mode 100644
index 0000000..5a56094
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/PaymentInfoService.java
@@ -0,0 +1,40 @@
+package com.atguigu.ssyx.payment.service;
+
+import com.atguigu.ssyx.model.order.PaymentInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.Map;
+
+/**
+ * ClassName: PaymentInfoService
+ * Package: com.atguigu.ssyx.payment.service
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:33
+ */
+
+public interface PaymentInfoService extends IService {
+ /**
+ * 根据orderNo查询支付订单
+ *
+ * @param orderNo
+ * @return
+ */
+ PaymentInfo getPaymentInfoByOrderNo(String orderNo);
+
+ /**
+ * 保存支付订单
+ *
+ * @param orderNo
+ * @return
+ */
+ PaymentInfo savePaymentInfo(String orderNo);
+
+ /**
+ * 支付成功
+ *
+ * @param orderNo
+ * @param resultMap
+ */
+ void paySuccess(String orderNo, Map resultMap);
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/WeixinService.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/WeixinService.java
new file mode 100644
index 0000000..530f535
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/WeixinService.java
@@ -0,0 +1,28 @@
+package com.atguigu.ssyx.payment.service;
+
+import java.util.Map;
+
+/**
+ * ClassName: WeixinService
+ * Package: com.atguigu.ssyx.payment.controller.payment.service
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:32
+ */
+public interface WeixinService {
+ /**
+ * 调用微信支付系统生成预付单
+ *
+ * @param orderNo
+ * @return
+ */
+ Map createJsapi(String orderNo);
+
+ /**
+ * 调用微信支付系统接口查询订单支付状态
+ *
+ * @param orderNo
+ * @return
+ */
+ Map queryPayStatus(String orderNo);
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/impl/PaymentInfoServiceImpl.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/impl/PaymentInfoServiceImpl.java
new file mode 100644
index 0000000..bf53c69
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/impl/PaymentInfoServiceImpl.java
@@ -0,0 +1,111 @@
+package com.atguigu.ssyx.payment.service.impl;
+
+import com.atguigu.ssyx.client.order.OrderFeignClient;
+import com.atguigu.ssyx.common.exception.SsyxException;
+import com.atguigu.ssyx.common.result.ResultCodeEnum;
+import com.atguigu.ssyx.enums.PaymentStatus;
+import com.atguigu.ssyx.enums.PaymentType;
+import com.atguigu.ssyx.model.order.OrderInfo;
+import com.atguigu.ssyx.model.order.PaymentInfo;
+import com.atguigu.ssyx.mq.constant.MqConst;
+import com.atguigu.ssyx.mq.service.RabbitService;
+import com.atguigu.ssyx.payment.mapper.PaymentInfoMapper;
+import com.atguigu.ssyx.payment.service.PaymentInfoService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ *
+ * 支付信息表 服务实现类
+ *
+ *
+ * @author atguigu
+ * @since 2023-10-12
+ */
+@Service
+public class PaymentInfoServiceImpl extends ServiceImpl implements PaymentInfoService {
+
+
+ @Autowired
+ private OrderFeignClient orderFeignClient;
+
+ @Autowired
+ private RabbitService rabbitService;
+
+ /**
+ * 根据orderNo查询支付订单
+ *
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public PaymentInfo getPaymentInfoByOrderNo(String orderNo) {
+ return baseMapper.selectOne(new LambdaQueryWrapper().eq(PaymentInfo::getOrderNo, orderNo));
+ }
+
+ /**
+ * 保存支付订单
+ *
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public PaymentInfo savePaymentInfo(String orderNo) {
+ //远程调用调用,根据orderNo查询订单信息
+ OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderNo);
+ if (orderInfo == null) {
+ throw new SsyxException(ResultCodeEnum.DATA_ERROR);
+ }
+ //封装到PaymentInfo对象
+ PaymentInfo paymentInfo = new PaymentInfo();
+ paymentInfo.setCreateTime(new Date());
+ paymentInfo.setOrderId(orderInfo.getId());
+ paymentInfo.setPaymentType(PaymentType.WEIXIN);
+ paymentInfo.setUserId(orderInfo.getUserId());
+ paymentInfo.setOrderNo(orderInfo.getOrderNo());
+ paymentInfo.setPaymentStatus(PaymentStatus.UNPAID);
+ String subject = "userID:" + orderInfo.getUserId() + "下订单";
+ paymentInfo.setSubject(subject);
+ //paymentInfo.setTotalAmount(orderInfo.getTotalAmount());
+ //TODO 为了测试
+ paymentInfo.setTotalAmount(new BigDecimal("0.01"));
+
+ //调用方法实现添加
+ baseMapper.insert(paymentInfo);
+ return paymentInfo;
+ }
+
+ /**
+ * 支付成功
+ *
+ * @param orderNo
+ * @param resultMap
+ */
+ @Override
+ public void paySuccess(String orderNo, Map resultMap) {
+ //1 查询当前订单支付记录表状态是否是已经支付
+ PaymentInfo paymentInfo = baseMapper.selectOne(
+ new LambdaQueryWrapper()
+ .eq(PaymentInfo::getOrderNo, orderNo)
+ );
+ if (paymentInfo.getPaymentStatus() != PaymentStatus.UNPAID) {
+ return;
+ }
+
+ //2 如果支付记录表支付状态没有支付,更新
+ paymentInfo.setPaymentStatus(PaymentStatus.PAID);
+ paymentInfo.setTradeNo(resultMap.get("transaction_id"));
+ paymentInfo.setCallbackContent(resultMap.toString());
+ baseMapper.updateById(paymentInfo);
+
+ //3 整合RabbitMQ实现 修改订单记录已经支付,库存扣减
+ rabbitService.sendMessage(MqConst.EXCHANGE_PAY_DIRECT,
+ MqConst.ROUTING_PAY_SUCCESS, orderNo);
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/impl/WeXinServiceImpl.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/impl/WeXinServiceImpl.java
new file mode 100644
index 0000000..7fbc428
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/service/impl/WeXinServiceImpl.java
@@ -0,0 +1,140 @@
+package com.atguigu.ssyx.payment.service.impl;
+
+import com.atguigu.ssyx.common.constant.RedisConst;
+import com.atguigu.ssyx.model.order.PaymentInfo;
+import com.atguigu.ssyx.payment.service.PaymentInfoService;
+import com.atguigu.ssyx.payment.service.WeixinService;
+import com.atguigu.ssyx.payment.utils.ConstantPropertiesUtils;
+import com.atguigu.ssyx.payment.utils.HttpClient;
+import com.atguigu.ssyx.vo.user.UserLoginVo;
+import com.github.wxpay.sdk.WXPayUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ClassName: WeXinServiceImpl
+ * Package: com.atguigu.ssyx.payment.service.impl
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:33
+ */
+@Service
+public class WeXinServiceImpl implements WeixinService {
+
+
+ @Autowired
+ private PaymentInfoService paymentInfoService;
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ /**
+ * 调用微信支付系统生成预付单
+ *
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public Map createJsapi(String orderNo) {
+ //1 向payment_info支付记录表添加记录,目前支付状态:正在支付中
+ PaymentInfo paymentInfo = paymentInfoService.getPaymentInfoByOrderNo(orderNo);
+ if (paymentInfo == null) {
+ paymentInfo = paymentInfoService.savePaymentInfo(orderNo);
+ }
+
+ //2 封装微信支付系统接口需要参数
+ Map paramMap = new HashMap<>();
+ paramMap.put("appid", ConstantPropertiesUtils.APPID);
+ paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
+ paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
+ paramMap.put("body", paymentInfo.getSubject());
+ paramMap.put("out_trade_no", paymentInfo.getOrderNo());
+ int totalFee = paymentInfo.getTotalAmount().multiply(new BigDecimal(100)).intValue();
+ paramMap.put("total_fee", String.valueOf(totalFee));
+ paramMap.put("spbill_create_ip", "127.0.0.1");
+ paramMap.put("notify_url", ConstantPropertiesUtils.NOTIFYURL);
+ paramMap.put("trade_type", "JSAPI");
+
+ //openid
+ UserLoginVo userLoginVo = (UserLoginVo) redisTemplate.opsForValue().get(RedisConst.USER_LOGIN_KEY_PREFIX + paymentInfo.getUserId());
+ if (null != userLoginVo && !StringUtils.isEmpty(userLoginVo.getOpenId())) {
+ paramMap.put("openid", userLoginVo.getOpenId());
+ } else {
+ paramMap.put("openid", "odo3j4q2KskkbbW-krfE-cAxUnzU1");
+ }
+ //3 使用HttpClient调用微信支付系统接口
+ HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
+ //设置参数,xml格式
+ try {
+ client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
+ client.setHttps(true);
+ client.post();
+
+ //4 调用微信支付系统接口之后,返回结果 prepay_id
+ String xml = client.getContent();
+ Map resultMap = WXPayUtil.xmlToMap(xml);
+
+ //5 封装需要数据-包含预付单标识 prepay_id
+ Map parameterMap = new HashMap<>();
+ String prepayId = String.valueOf(resultMap.get("prepay_id"));
+ String packages = "prepay_id=" + prepayId;
+ parameterMap.put("appId", ConstantPropertiesUtils.APPID);
+ parameterMap.put("nonceStr", resultMap.get("nonce_str"));
+ parameterMap.put("package", packages);
+ parameterMap.put("signType", "MD5");
+ parameterMap.put("timeStamp", String.valueOf(new Date().getTime()));
+ String sign = WXPayUtil.generateSignature(parameterMap, ConstantPropertiesUtils.PARTNERKEY);
+
+ //返回结果
+ Map result = new HashMap();
+ result.put("timeStamp", parameterMap.get("timeStamp"));
+ result.put("nonceStr", parameterMap.get("nonceStr"));
+ result.put("signType", "MD5");
+ result.put("paySign", sign);
+ result.put("package", packages);
+
+ //6 返回结果
+ return result;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 调用微信支付系统接口查询订单支付状态
+ *
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public Map queryPayStatus(String orderNo) {
+ //封装数据、
+ Map paramMap = new HashMap();
+ paramMap.put("appid", ConstantPropertiesUtils.APPID);
+ paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
+ paramMap.put("out_trade_no", orderNo);
+ paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
+
+ //2、设置请求
+ HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
+ try {
+ client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
+ client.setHttps(true);
+ client.post();
+
+ //3 得到返回结果
+ String xml = client.getContent();
+ Map stringMap = WXPayUtil.xmlToMap(xml);
+ return stringMap;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/utils/ConstantPropertiesUtils.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/utils/ConstantPropertiesUtils.java
new file mode 100644
index 0000000..b464eca
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/utils/ConstantPropertiesUtils.java
@@ -0,0 +1,42 @@
+package com.atguigu.ssyx.payment.utils;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * ClassName: ConstantPropertiesUtils
+ * Package: com.atguigu.ssyx.payment.utils
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:48
+ */
+@Component
+public class ConstantPropertiesUtils implements InitializingBean {
+
+ public static String APPID;
+ public static String PARTNER;
+ public static String PARTNERKEY;
+ public static String NOTIFYURL;
+ public static String CERT;
+ @Value("${weixin.appid}")
+ private String appid;
+ @Value("${weixin.partner}")
+ private String partner;
+ @Value("${weixin.partnerkey}")
+ private String partnerkey;
+ @Value("${weixin.notifyurl}")
+ private String notifyurl;
+ @Value("${weixin.cert}")
+ private String cert;
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ APPID = appid;
+ PARTNER = partner;
+ PARTNERKEY = partnerkey;
+ NOTIFYURL = notifyurl;
+ CERT = cert;
+ }
+}
+
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/utils/HttpClient.java b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/utils/HttpClient.java
new file mode 100644
index 0000000..4bfe322
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/java/com/atguigu/ssyx/payment/utils/HttpClient.java
@@ -0,0 +1,207 @@
+package com.atguigu.ssyx.payment.utils;
+
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.*;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContextBuilder;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.http.util.EntityUtils;
+
+import javax.net.ssl.SSLContext;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ClassName: HttpClient
+ * Package: com.atguigu.ssyx.payment.utils
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 10:47
+ */
+public class HttpClient {
+
+ private String url;
+ private Map param;
+ private int statusCode;
+ private String content;
+ private String xmlParam;
+ private boolean isHttps;
+ private boolean isCert = false;
+ //证书密码 微信商户号(mch_id)
+ private String certPassword;
+
+ public HttpClient(String url, Map param) {
+ this.url = url;
+ this.param = param;
+ }
+
+ public HttpClient(String url) {
+ this.url = url;
+ }
+
+ public boolean isHttps() {
+ return isHttps;
+ }
+
+ public void setHttps(boolean isHttps) {
+ this.isHttps = isHttps;
+ }
+
+ public boolean isCert() {
+ return isCert;
+ }
+
+ public void setCert(boolean cert) {
+ isCert = cert;
+ }
+
+ public String getXmlParam() {
+ return xmlParam;
+ }
+
+ public void setXmlParam(String xmlParam) {
+ this.xmlParam = xmlParam;
+ }
+
+ public String getCertPassword() {
+ return certPassword;
+ }
+
+ public void setCertPassword(String certPassword) {
+ this.certPassword = certPassword;
+ }
+
+ public void setParameter(Map map) {
+ param = map;
+ }
+
+ public void addParameter(String key, String value) {
+ if (param == null)
+ param = new HashMap();
+ param.put(key, value);
+ }
+
+ public void post() throws IOException {
+ HttpPost http = new HttpPost(url);
+ setEntity(http);
+ execute(http);
+ }
+
+ public void put() throws IOException {
+ HttpPut http = new HttpPut(url);
+ setEntity(http);
+ execute(http);
+ }
+
+ public void get() throws IOException {
+ if (param != null) {
+ StringBuilder url = new StringBuilder(this.url);
+ boolean isFirst = true;
+ for (String key : param.keySet()) {
+ if (isFirst)
+ url.append("?");
+ else
+ url.append("&");
+ url.append(key).append("=").append(param.get(key));
+ }
+ this.url = url.toString();
+ }
+ HttpGet http = new HttpGet(url);
+ execute(http);
+ }
+
+ /**
+ * set http post,put param
+ */
+ private void setEntity(HttpEntityEnclosingRequestBase http) {
+ if (param != null) {
+ List nvps = new LinkedList();
+ for (String key : param.keySet())
+ nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
+ http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
+ }
+ if (xmlParam != null) {
+ http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
+ }
+ }
+
+ private void execute(HttpUriRequest http) throws
+ IOException {
+ CloseableHttpClient httpClient = null;
+ try {
+ if (isHttps) {
+ if (isCert) {
+ FileInputStream inputStream = new FileInputStream(new File(ConstantPropertiesUtils.CERT));
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ char[] partnerId2charArray = certPassword.toCharArray();
+ keystore.load(inputStream, partnerId2charArray);
+ SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();
+ SSLConnectionSocketFactory sslsf =
+ new SSLConnectionSocketFactory(sslContext,
+ new String[]{"TLSv1"},
+ null,
+ SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
+ } else {
+ SSLContext sslContext = new SSLContextBuilder()
+ .loadTrustMaterial(null, new TrustStrategy() {
+ // 信任所有
+ public boolean isTrusted(X509Certificate[] chain,
+ String authType)
+ throws CertificateException {
+ return true;
+ }
+ }).build();
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
+ sslContext);
+ httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
+ .build();
+ }
+ } else {
+ httpClient = HttpClients.createDefault();
+ }
+ CloseableHttpResponse response = httpClient.execute(http);
+ try {
+ if (response != null) {
+ if (response.getStatusLine() != null)
+ statusCode = response.getStatusLine().getStatusCode();
+ HttpEntity entity = response.getEntity();
+ // 响应内容
+ content = EntityUtils.toString(entity, Consts.UTF_8);
+ }
+ } finally {
+ response.close();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ httpClient.close();
+ }
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public String getContent() throws ParseException, IOException {
+ return content;
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/resources/application-dev.yml b/guigu-ssyx-parent/service/service-payment/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..d91db2f
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/resources/application-dev.yml
@@ -0,0 +1,60 @@
+server:
+ port: 8210
+mybatis-plus:
+ type-enums-package: com.atguigu.ssyx.enums
+ configuration:
+ log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+ mapper-locations: classpath:mapper/*.xml
+feign:
+ sentinel:
+ enabled: true
+ client:
+ config:
+ default: #配置全局的feign的调用超时时间 如果 有指定的服务配置 默认的配置不会生效
+ connectTimeout: 30000 # 指定的是 消费者 连接服务提供者的连接超时时间 是否能连接 单位是毫秒
+ readTimeout: 50000 # 指定的是调用服务提供者的 服务 的超时时间() 单位是毫秒
+spring:
+ main:
+ allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
+ rabbitmq:
+ host: 43.143.164.194
+ port: 5672
+ username: guest
+ password: guest
+ redis:
+ host: 82.157.68.223
+ port: 6379
+ database: 0
+ timeout: 1800000
+ password:
+ lettuce:
+ pool:
+ max-active: 20 #最大连接数
+ max-wait: -1 #最大阻塞等待时间(负数表示没限制)
+ max-idle: 5 #最大空闲
+ min-idle: 0 #最小空闲
+ datasource:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://82.157.68.223:3306/shequ-order?characterEncoding=utf-8&useSSL=false
+ username: shequ-order
+ password: shequ-order
+ hikari:
+ connection-test-query: SELECT 1
+ connection-timeout: 60000
+ idle-timeout: 500000
+ max-lifetime: 540000
+ maximum-pool-size: 5
+ minimum-idle: 3
+ pool-name: GuliHikariPool
+ jackson:
+ date-format: yyyy-MM-dd HH:mm:ss
+ time-zone: GMT+8
+# 微信
+weixin:
+ #小程序微信公众平台appId
+ appid: wxcc651fcbab275e33
+ partner: 1481962542
+ partnerkey: MXb72b9RfshXZD4FRGV5KLqmv5bx9LT9
+ notifyurl: http://gmall-prod.atguigu.cn/api/payment/weixin/notify
+ cert: /Users/yovinchen/project/Java/ssyx/guigu-ssyx-parent/service/service-payment/src/main/resources/cert/apiclient_cert.p12
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/resources/application.yml b/guigu-ssyx-parent/service/service-payment/src/main/resources/application.yml
new file mode 100644
index 0000000..ec33dce
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-payment/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+spring:
+ application:
+ name: service-payment
+ profiles:
+ active: dev
+ cloud:
+ nacos:
+ discovery:
+ server-addr: 82.157.68.223:8848
+ username: nacos
+ password: nacos
diff --git a/guigu-ssyx-parent/service/service-payment/src/main/resources/cert/apiclient_cert.p12 b/guigu-ssyx-parent/service/service-payment/src/main/resources/cert/apiclient_cert.p12
new file mode 100644
index 0000000..3413e3b
Binary files /dev/null and b/guigu-ssyx-parent/service/service-payment/src/main/resources/cert/apiclient_cert.p12 differ
diff --git a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/mapper/SkuInfoMapper.java b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/mapper/SkuInfoMapper.java
index ad68b9c..4064870 100644
--- a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/mapper/SkuInfoMapper.java
+++ b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/mapper/SkuInfoMapper.java
@@ -39,4 +39,12 @@ public interface SkuInfoMapper extends BaseMapper {
* @param skuNum
*/
void unlockStock(@Param("skuId") Long skuId, @Param("skuNum") Integer skuNum);
+
+ /**
+ * 减库存
+ *
+ * @param skuId
+ * @param skuNum
+ */
+ void minusStock(@Param("skuId") Long skuId, @Param("skuNum") Integer skuNum);
}
diff --git a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/receiver/StockReceiver.java b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/receiver/StockReceiver.java
new file mode 100644
index 0000000..b6cd405
--- /dev/null
+++ b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/receiver/StockReceiver.java
@@ -0,0 +1,43 @@
+package com.atguigu.ssyx.product.receiver;
+
+import com.atguigu.ssyx.mq.constant.MqConst;
+import com.atguigu.ssyx.product.service.SkuInfoService;
+import com.rabbitmq.client.Channel;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+
+/**
+ * ClassName: StockReceiver
+ * Package: com.atguigu.ssyx.product.receiver
+ *
+ * @author yovinchen
+ * @Create 2023/10/13 15:05
+ */
+@Component
+public class StockReceiver {
+
+ @Autowired
+ private SkuInfoService skuInfoService;
+
+ /**
+ * 扣减库存成功,更新订单状态
+ *
+ * @param orderNo
+ * @throws IOException
+ */
+ @RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_MINUS_STOCK, durable = "true"), exchange = @Exchange(value = MqConst.EXCHANGE_ORDER_DIRECT), key = {MqConst.ROUTING_MINUS_STOCK}))
+ public void minusStock(String orderNo, Message message, Channel channel) throws IOException {
+ if (!StringUtils.isEmpty(orderNo)) {
+ skuInfoService.minusStock(orderNo);
+ }
+ channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+ }
+}
diff --git a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/SkuInfoService.java b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/SkuInfoService.java
index 2758a49..3597e46 100644
--- a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/SkuInfoService.java
+++ b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/SkuInfoService.java
@@ -115,4 +115,11 @@ public interface SkuInfoService extends IService {
* @return
*/
Boolean checkAndLock(List skuStockLockVoList, String orderNo);
+
+ /**
+ * 扣减库存成功,更新订单状态
+ *
+ * @param orderNo
+ */
+ void minusStock(String orderNo);
}
diff --git a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/impl/SkuInfoServiceImpl.java b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/impl/SkuInfoServiceImpl.java
index 7d01ca2..db3a6fe 100644
--- a/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/impl/SkuInfoServiceImpl.java
+++ b/guigu-ssyx-parent/service/service-product/src/main/java/com/atguigu/ssyx/product/service/impl/SkuInfoServiceImpl.java
@@ -312,9 +312,7 @@ public class SkuInfoServiceImpl extends ServiceImpl impl
//获取第一页数据,每页显示三条记录
Page pageParam = new Page<>(1, 3);
//调用方法查询
- IPage skuInfoPage = baseMapper.selectPage(pageParam, new LambdaQueryWrapper().eq(SkuInfo::getIsNewPerson, 1)
- .eq(SkuInfo::getPublishStatus, 1)
- .orderByDesc(SkuInfo::getStock));
+ IPage skuInfoPage = baseMapper.selectPage(pageParam, new LambdaQueryWrapper().eq(SkuInfo::getIsNewPerson, 1).eq(SkuInfo::getPublishStatus, 1).orderByDesc(SkuInfo::getStock));
return skuInfoPage.getRecords();
}
@@ -333,31 +331,47 @@ public class SkuInfoServiceImpl extends ServiceImpl impl
}
//2 遍历skuStockLockVoList得到每个商品,验证库存并锁定库存,具备原子性
- skuStockLockVoList.stream()
- .forEach(skuStockLockVo -> {
- this.checkLock(skuStockLockVo);
- });
+ skuStockLockVoList.stream().forEach(skuStockLockVo -> {
+ this.checkLock(skuStockLockVo);
+ });
//3 只要有一个商品锁定失败,所有锁定成功的商品都解锁
- boolean flag = skuStockLockVoList.stream()
- .anyMatch(skuStockLockVo -> !skuStockLockVo.getIsLock());
+ boolean flag = skuStockLockVoList.stream().anyMatch(skuStockLockVo -> !skuStockLockVo.getIsLock());
if (flag) {
//所有锁定成功的商品都解锁
- skuStockLockVoList.stream()
- .filter(SkuStockLockVo::getIsLock)
- .forEach(skuStockLockVo -> {
- baseMapper.unlockStock(skuStockLockVo.getSkuId(), skuStockLockVo.getSkuNum());
- });
+ skuStockLockVoList.stream().filter(SkuStockLockVo::getIsLock).forEach(skuStockLockVo -> {
+ baseMapper.unlockStock(skuStockLockVo.getSkuId(), skuStockLockVo.getSkuNum());
+ });
//返回失败的状态
return false;
}
//4 如果所有商品都锁定成功了,redis缓存相关数据,为了方便后面解锁和减库存
- redisTemplate.opsForValue()
- .set(RedisConst.SROCK_INFO + orderNo, skuStockLockVoList);
+ redisTemplate.opsForValue().set(RedisConst.SROCK_INFO + orderNo, skuStockLockVoList);
return true;
}
+ /**
+ * 扣减库存成功,更新订单状态
+ *
+ * @param orderNo
+ */
+ @Override
+ public void minusStock(String orderNo) {
+ //从redis获取锁定库存信息
+ List skuStockLockVoList = (List) redisTemplate.opsForValue().get(RedisConst.SROCK_INFO + orderNo);
+ if (CollectionUtils.isEmpty(skuStockLockVoList)) {
+ return;
+ }
+ //遍历集合,得到每个对象,减库存
+ skuStockLockVoList.forEach(skuStockLockVo -> {
+ baseMapper.minusStock(skuStockLockVo.getSkuId(), skuStockLockVo.getSkuNum());
+ });
+
+ //删除redis数据
+ redisTemplate.delete(RedisConst.SROCK_INFO + orderNo);
+ }
+
//2 遍历skuStockLockVoList得到每个商品,验证库存并锁定库存,具备原子性
private void checkLock(SkuStockLockVo skuStockLockVo) {
//获取锁