From 1afbf9e4200dbaf418fb908507421361d471a822 Mon Sep 17 00:00:00 2001 From: subaixi Date: Thu, 3 Oct 2024 23:16:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=A8=A1=E6=8B=9F=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notify/PayNotifyController.java | 117 ++++++++++++++++++ .../sky/controller/user/OrderController.java | 35 +++++- .../main/java/com/sky/mapper/OrderMapper.java | 15 +++ .../main/java/com/sky/mapper/UserMapper.java | 8 ++ .../java/com/sky/service/OrderService.java | 15 +++ .../sky/service/impl/OrderServiceImpl.java | 72 +++++++++-- .../src/main/resources/application-dev.yml | 7 ++ sky-server/src/main/resources/application.yml | 7 ++ .../src/main/resources/mapper/OrderMapper.xml | 32 ++++- 9 files changed, 292 insertions(+), 16 deletions(-) create mode 100644 sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java diff --git a/sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java b/sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java new file mode 100644 index 0000000..df59cf4 --- /dev/null +++ b/sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java @@ -0,0 +1,117 @@ +package com.sky.controller.notify; + +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.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +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 { + @Autowired + private OrderService orderService; + @Autowired + private WeChatProperties weChatProperties; + + /** + * 支付成功回调 + * + * @param request + */ + @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 + * @return + * @throws 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 + * @return + * @throws 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 + */ + 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/controller/user/OrderController.java b/sky-server/src/main/java/com/sky/controller/user/OrderController.java index d976800..26c3559 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,17 +1,16 @@ 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.beans.factory.annotation.Autowired; -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.*; @RestController("userOrderController") @RequestMapping("/user/order") @@ -34,4 +33,32 @@ 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); +// } + + /** + * 订单支付(修改版,直接支付成功) + * @param ordersPaymentDTO + * @return + */ + @PutMapping("/payment") + @ApiOperation("订单支付") + public Result payment(@RequestBody OrdersPaymentDTO ordersPaymentDTO) throws Exception { + log.info("订单支付:{}", ordersPaymentDTO); + //业务处理,修改订单状态、来单提醒 + orderService.paySuccess(ordersPaymentDTO.getOrderNumber()); + return Result.success(null); + } } 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 e0e326b..573a62f 100644 --- a/sky-server/src/main/java/com/sky/mapper/OrderMapper.java +++ b/sky-server/src/main/java/com/sky/mapper/OrderMapper.java @@ -2,6 +2,7 @@ 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 { @@ -10,4 +11,18 @@ public interface OrderMapper { * @param orders */ 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 929a34f..1faebaa 100644 --- a/sky-server/src/main/java/com/sky/mapper/UserMapper.java +++ b/sky-server/src/main/java/com/sky/mapper/UserMapper.java @@ -20,4 +20,12 @@ public interface UserMapper { * @param user */ void insert(User user); + + /** + * 根据用户id查询用户信息 + * @param userId + * @return + */ + @Select("select * from user where id = #{userId}") + 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 4aa10ed..9cb1030 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 { @@ -10,4 +12,17 @@ public interface OrderService { * @return */ OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO); + + /** + * 订单支付 + * @param ordersPaymentDTO + * @return + */ + OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception; + + /** + * 支付成功,修改订单状态 + * @param outTradeNo + */ + 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 ecc3785..3086684 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.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -29,15 +29,16 @@ public class OrderServiceImpl implements OrderService { @Autowired private OrderMapper orderMapper; - @Autowired private OrderDetailMapper orderDetailMapper; - @Autowired private AddressBookMapper addressBookMapper; - @Autowired private ShoppingCartMapper shoppingCartMapper; + @Autowired + private WeChatPayUtil weChatPayUtil; + @Autowired + private UserMapper userMapper; /** * 提交订单 @@ -98,4 +99,53 @@ public class OrderServiceImpl implements OrderService { .build(); return orderSubmitVO; } + + /** + * 订单支付 + * @param ordersPaymentDTO + * @return + */ + 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 + */ + 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 39d244b..06198ac 100644 --- a/sky-server/src/main/resources/application-dev.yml +++ b/sky-server/src/main/resources/application-dev.yml @@ -18,3 +18,10 @@ sky: wechat: appid: wx34fbbbace9943d4a secret: 3e5f899be36fa508bb41dc5611bff0c7 + mchid: 1561414331 + mchSerialNo: 4B3B3DC35414AD50B1B755BAF8DE9CC7CF407606 + privateKeyFilePath: D:\apiclient_key.pem + apiV3Key: CZBK51236435wxpay435434323FFDuv3 + weChatPayCertFilePath: D:\wechatpay_166D96F876F45C7D07CE98952A96EC980368ACFC.pem + notifyUrl: https://www.weixin.qq.com/wxpay/pay.php + refundNotifyUrl: https://www.weixin.qq.com/wxpay/pay.php diff --git a/sky-server/src/main/resources/application.yml b/sky-server/src/main/resources/application.yml index c154165..cac93fb 100644 --- a/sky-server/src/main/resources/application.yml +++ b/sky-server/src/main/resources/application.yml @@ -57,3 +57,10 @@ sky: wechat: appid: ${sky.wechat.appid} secret: ${sky.wechat.secret} + mchid: ${sky.wechat.mchid} + mchSerialNo: ${sky.wechat.mchSerialNo} + privateKeyFilePath: ${sky.wechat.privateKeyFilePath} + apiV3Key: ${sky.wechat.apiV3Key} + weChatPayCertFilePath: ${sky.wechat.weChatPayCertFilePath} + notifyUrl: ${sky.wechat.notifyUrl} + refundNotifyUrl: ${sky.wechat.refundNotifyUrl} diff --git a/sky-server/src/main/resources/mapper/OrderMapper.xml b/sky-server/src/main/resources/mapper/OrderMapper.xml index 6db298d..2b8acd2 100644 --- a/sky-server/src/main/resources/mapper/OrderMapper.xml +++ b/sky-server/src/main/resources/mapper/OrderMapper.xml @@ -11,6 +11,36 @@ (#{number}, #{status}, #{userId}, #{addressBookId}, #{orderTime}, #{checkoutTime}, #{payMethod}, #{payStatus}, #{amount}, #{remark}, #{phone}, #{address}, #{consignee}, #{estimatedDeliveryTime}, #{deliveryStatus}, #{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} +