From c6cae41822406045f79d0cb49a2c58284979fa95 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Wed, 10 Jan 2024 13:43:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98-=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E6=94=AF=E4=BB=98=E8=B5=84=E8=B4=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sky/controller/user/OrderController.java | 22 +++- .../controller/user/PayNotifyController.java | 119 ++++++++++++++++++ .../main/java/com/sky/mapper/OrderMapper.java | 16 +++ .../main/java/com/sky/mapper/UserMapper.java | 12 +- .../java/com/sky/service/OrderService.java | 17 +++ .../sky/service/impl/OrderServiceImpl.java | 70 +++++++++-- .../src/main/resources/application-dev.yml | 9 +- sky-server/src/main/resources/application.yml | 9 +- .../src/main/resources/mapper/OrderMapper.xml | 33 +++++ .../src/main/resources/mapper/UserMapper.xml | 7 ++ 10 files changed, 299 insertions(+), 15 deletions(-) create mode 100644 sky-server/src/main/java/com/sky/controller/user/PayNotifyController.java diff --git a/sky-server/src/main/java/com/sky/controller/user/OrderController.java b/sky-server/src/main/java/com/sky/controller/user/OrderController.java index a42749b..8d7cd94 100644 --- a/sky-server/src/main/java/com/sky/controller/user/OrderController.java +++ b/sky-server/src/main/java/com/sky/controller/user/OrderController.java @@ -1,16 +1,15 @@ package com.sky.controller.user; +import com.sky.dto.OrdersPaymentDTO; import com.sky.dto.OrdersSubmitDTO; import com.sky.result.Result; import com.sky.service.OrderService; +import com.sky.vo.OrderPaymentVO; import com.sky.vo.OrderSubmitVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -35,4 +34,19 @@ public class OrderController { OrderSubmitVO orderSubmitVO = orderService.submitOrder(ordersSubmitDTO); return Result.success(orderSubmitVO); } + + /** + * 订单支付 + * + * @param ordersPaymentDTO + * @return + */ + @PutMapping("/payment") + @ApiOperation("订单支付") + public Result payment(@RequestBody OrdersPaymentDTO ordersPaymentDTO) throws Exception { + log.info("订单支付:{}", ordersPaymentDTO); + OrderPaymentVO orderPaymentVO = orderService.payment(ordersPaymentDTO); + log.info("生成预支付交易单:{}", orderPaymentVO); + return Result.success(orderPaymentVO); + } } diff --git a/sky-server/src/main/java/com/sky/controller/user/PayNotifyController.java b/sky-server/src/main/java/com/sky/controller/user/PayNotifyController.java new file mode 100644 index 0000000..0c93d21 --- /dev/null +++ b/sky-server/src/main/java/com/sky/controller/user/PayNotifyController.java @@ -0,0 +1,119 @@ +package com.sky.controller.user; + +import com.alibaba.druid.support.json.JSONUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.sky.properties.WeChatProperties; +import com.sky.service.OrderService; +import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.entity.ContentType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; + +/** + * 支付回调相关接口 + */ +@RestController +@RequestMapping("/notify") +@Slf4j +public class PayNotifyController { + @Resource + private OrderService orderService; + @Resource + private WeChatProperties weChatProperties; + + /** + * 支付成功回调 + * + * @param request HttpServletRequest + */ + @RequestMapping("/paySuccess") + public void paySuccessNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + // 读取数据 + String body = readData(request); + log.info("支付成功回调:{}", body); + + // 数据解密 + String plainText = decryptData(body); + log.info("解密后的文本:{}", plainText); + + JSONObject jsonObject = JSON.parseObject(plainText); + String outTradeNo = jsonObject.getString("out_trade_no");// 商户平台订单号 + String transactionId = jsonObject.getString("transaction_id");// 微信支付交易号 + + log.info("商户平台订单号:{}", outTradeNo); + log.info("微信支付交易号:{}", transactionId); + + // 业务处理,修改订单状态、来单提醒 + orderService.paySuccess(outTradeNo); + + // 给微信响应 + responseToWeixin(response); + } + + /** + * 读取数据 + * + * @param request HttpServletRequest + * @return String + * @throws Exception exception + */ + private String readData(HttpServletRequest request) throws Exception { + BufferedReader reader = request.getReader(); + StringBuilder result = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + if (result.length() > 0) { + result.append("\n"); + } + result.append(line); + } + return result.toString(); + } + + /** + * 数据解密 + * + * @param body String + * @return String + * @throws Exception exception + */ + private String decryptData(String body) throws Exception { + JSONObject resultObject = JSON.parseObject(body); + JSONObject resource = resultObject.getJSONObject("resource"); + String ciphertext = resource.getString("ciphertext"); + String nonce = resource.getString("nonce"); + String associatedData = resource.getString("associated_data"); + + AesUtil aesUtil = new AesUtil(weChatProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8)); + // 密文解密 + String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), + nonce.getBytes(StandardCharsets.UTF_8), + ciphertext); + + return plainText; + } + + /** + * 给微信响应 + * + * @param response HttpServletResponse + */ + private void responseToWeixin(HttpServletResponse response) throws Exception { + response.setStatus(200); + HashMap map = new HashMap<>(); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + response.setHeader("Content-type", ContentType.APPLICATION_JSON.toString()); + response.getOutputStream().write(JSONUtils.toJSONString(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } +} diff --git a/sky-server/src/main/java/com/sky/mapper/OrderMapper.java b/sky-server/src/main/java/com/sky/mapper/OrderMapper.java index 12da6fe..6778822 100644 --- a/sky-server/src/main/java/com/sky/mapper/OrderMapper.java +++ b/sky-server/src/main/java/com/sky/mapper/OrderMapper.java @@ -2,9 +2,25 @@ package com.sky.mapper; import com.sky.entity.Orders; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; @Mapper public interface OrderMapper { // 向订单中插入1条数据 void insert(Orders orders); + + /** + * 根据订单号查询订单 + * + * @param orderNumber + */ + @Select("select * from orders where number = #{orderNumber}") + Orders getByNumber(String orderNumber); + + /** + * 修改订单信息 + * + * @param orders + */ + void update(Orders orders); } diff --git a/sky-server/src/main/java/com/sky/mapper/UserMapper.java b/sky-server/src/main/java/com/sky/mapper/UserMapper.java index 56a944e..d08719b 100644 --- a/sky-server/src/main/java/com/sky/mapper/UserMapper.java +++ b/sky-server/src/main/java/com/sky/mapper/UserMapper.java @@ -8,14 +8,24 @@ public interface UserMapper { /** * 根据用户id查询用户 - * @param openid String + * + * @param openid String * @return User */ User getByOpenid(String openid); /** * 如果为新用户自动完成注册 + * * @param user User */ void insert(User user); + + /** + * 当前登录用户id + * + * @param userId Long + * @return User + */ + User getById(Long userId); } diff --git a/sky-server/src/main/java/com/sky/service/OrderService.java b/sky-server/src/main/java/com/sky/service/OrderService.java index 7ca2408..9208e54 100644 --- a/sky-server/src/main/java/com/sky/service/OrderService.java +++ b/sky-server/src/main/java/com/sky/service/OrderService.java @@ -1,6 +1,8 @@ package com.sky.service; +import com.sky.dto.OrdersPaymentDTO; import com.sky.dto.OrdersSubmitDTO; +import com.sky.vo.OrderPaymentVO; import com.sky.vo.OrderSubmitVO; public interface OrderService { @@ -11,4 +13,19 @@ public interface OrderService { * @return OrderSubmitVO */ OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO); + + /** + * 订单支付 + * + * @param ordersPaymentDTO ordersPaymentDTO + * @return OrderPaymentVO + */ + OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception; + + /** + * 支付成功,修改订单状态 + * + * @param outTradeNo String + */ + void paySuccess(String outTradeNo); } diff --git a/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java b/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java index 4ea4ec6..f22dec1 100644 --- a/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java +++ b/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java @@ -1,25 +1,25 @@ package com.sky.service.impl; +import com.alibaba.fastjson.JSONObject; import com.sky.constant.MessageConstant; import com.sky.context.BaseContext; +import com.sky.dto.OrdersPaymentDTO; import com.sky.dto.OrdersSubmitDTO; -import com.sky.entity.AddressBook; -import com.sky.entity.OrderDetail; -import com.sky.entity.Orders; -import com.sky.entity.ShoppingCart; +import com.sky.entity.*; import com.sky.exception.AddressBookBusinessException; +import com.sky.exception.OrderBusinessException; import com.sky.exception.ShoppingCartBusinessException; -import com.sky.mapper.AddressBookMapper; -import com.sky.mapper.OrderDetailMapper; -import com.sky.mapper.OrderMapper; -import com.sky.mapper.ShoppingCartMapper; +import com.sky.mapper.*; import com.sky.service.OrderService; +import com.sky.utils.WeChatPayUtil; +import com.sky.vo.OrderPaymentVO; import com.sky.vo.OrderSubmitVO; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -34,6 +34,10 @@ public class OrderServiceImpl implements OrderService { private AddressBookMapper addressBookMapper; @Resource private ShoppingCartMapper shoppingCartMapper; + @Resource + private UserMapper userMapper; + @Resource + private WeChatPayUtil weChatPayUtil; /** * 用户下单 @@ -90,6 +94,56 @@ public class OrderServiceImpl implements OrderService { .orderNumber(orders.getNumber()) .orderAmount(orders.getAmount()).build(); } + + /** + * 订单支付 + * + * @param ordersPaymentDTO OrdersPaymentDTO + * @return OrderPaymentVO + */ + public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception { + // 当前登录用户id + Long userId = BaseContext.getCurrentId(); + User user = userMapper.getById(userId); + + // 调用微信支付接口,生成预支付交易单 + JSONObject jsonObject = weChatPayUtil.pay( + ordersPaymentDTO.getOrderNumber(), // 商户订单号 + new BigDecimal("0.01"), // 支付金额,单位 元 + "苍穹外卖订单", // 商品描述 + user.getOpenid() // 微信用户的openid + ); + + if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) { + throw new OrderBusinessException("该订单已支付"); + } + + OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class); + vo.setPackageStr(jsonObject.getString("package")); + + return vo; + } + + /** + * 支付成功,修改订单状态 + * + * @param outTradeNo String + */ + public void paySuccess(String outTradeNo) { + + // 根据订单号查询订单 + Orders ordersDB = orderMapper.getByNumber(outTradeNo); + + // 根据订单id更新订单的状态、支付方式、支付状态、结账时间 + Orders orders = Orders.builder() + .id(ordersDB.getId()) + .status(Orders.TO_BE_CONFIRMED) + .payStatus(Orders.PAID) + .checkoutTime(LocalDateTime.now()) + .build(); + + orderMapper.update(orders); + } } diff --git a/sky-server/src/main/resources/application-dev.yml b/sky-server/src/main/resources/application-dev.yml index 0f6b0b5..b1ca98b 100644 --- a/sky-server/src/main/resources/application-dev.yml +++ b/sky-server/src/main/resources/application-dev.yml @@ -18,4 +18,11 @@ sky: database: 1 wechat: appid: wx18e5556d7539757b - secret: ac06f1c49f90a2ed69f1a946d4981833 \ No newline at end of file + secret: ac06f1c49f90a2ed69f1a946d4981833 + mchid: 18012062876 + mch-serial-no: xcxzczx + private-key-file-path: sadsad + api-v3-key: dasdasd + we-chat-pay-cert-file-path: asdasds + notify-url: asdsada + refund-notify-url: asdasdsa \ No newline at end of file diff --git a/sky-server/src/main/resources/application.yml b/sky-server/src/main/resources/application.yml index 8d674c5..c3bc3d7 100644 --- a/sky-server/src/main/resources/application.yml +++ b/sky-server/src/main/resources/application.yml @@ -58,4 +58,11 @@ sky: bucket-name: ${sky.minio.bucket-name} wechat: appid: ${sky.wechat.appid} - secret: ${sky.wechat.secret} \ No newline at end of file + secret: ${sky.wechat.secret} + mchid: ${sky.wechat.mchid} + mch-serial-no: ${sky.wechat.mchSerialNo} + private-key-file-path: ${sky.wechat.privateKeyFilePath} + api-v3-key: ${sky.wechat.apiV3Key} + we-chat-pay-cert-file-path: ${sky.wechat.weChatPayCertFilePath} + notify-url: ${sky.wechat.notifyUrl} + refund-notify-url: ${sky.wechat.refundNotifyUrl} \ No newline at end of file diff --git a/sky-server/src/main/resources/mapper/OrderMapper.xml b/sky-server/src/main/resources/mapper/OrderMapper.xml index d747cc8..ee373ab 100644 --- a/sky-server/src/main/resources/mapper/OrderMapper.xml +++ b/sky-server/src/main/resources/mapper/OrderMapper.xml @@ -13,4 +13,37 @@ #{rejectionReason}, #{cancelTime}, #{estimatedDeliveryTime}, #{deliveryStatus}, #{deliveryTime}, #{packAmount}, #{tablewareNumber}, #{tablewareStatus}); + + + + update orders + + + cancel_reason=#{cancelReason}, + + + rejection_reason=#{rejectionReason}, + + + cancel_time=#{cancelTime}, + + + pay_status=#{payStatus}, + + + pay_method=#{payMethod}, + + + checkout_time=#{checkoutTime}, + + + status = #{status}, + + + delivery_time = #{deliveryTime} + + + where id = #{id} + + diff --git a/sky-server/src/main/resources/mapper/UserMapper.xml b/sky-server/src/main/resources/mapper/UserMapper.xml index edf7f29..41623e9 100644 --- a/sky-server/src/main/resources/mapper/UserMapper.xml +++ b/sky-server/src/main/resources/mapper/UserMapper.xml @@ -14,4 +14,11 @@ from user where openid = #{openid}; + + +