35302 字
约 117 分钟
39
appendix_G
无标签

附录G 订单服务模块源码详解

模块概览(面向 0 基础读者):

  • 负责课程付费订单创建、支付对接与结果通知。
  • 通过消息任务表 + MQ 确保支付成功与学习开通幂等。
  • 整合支付宝/微信支付 SDK,提供统一支付入口。

核心目录:

  • xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/orders/api
  • xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/service
  • xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper
  • xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/config
  • xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model

文件:xuecheng-plus-orders/api/main/com/xuecheng/orders/api/OrderController.java

package com.xuecheng.orders.api; // 声明类所在的包路径

import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.internal.util.AlipaySignature; // 导入 AlipaySignature 类
import com.alipay.api.request.AlipayTradeWapPayRequest; // 导入 AlipayTradeWapPayRequest 类
import com.xuecheng.base.exception.XueChengPlusException; // 导入 XueChengPlusException 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import com.xuecheng.orders.model.dto.AddOrderDto; // 导入 AddOrderDto 类
import com.xuecheng.orders.model.dto.PayRecordDto; // 导入 PayRecordDto 类
import com.xuecheng.orders.model.dto.PayStatusDto; // 导入 PayStatusDto 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类
import com.xuecheng.orders.service.OrderService; // 导入 OrderService 类
import com.xuecheng.orders.util.SecurityUtil; // 导入 SecurityUtil 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Controller; // 导入 Controller 类
import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 类
import org.springframework.web.bind.annotation.PostMapping; // 导入 PostMapping 类
import org.springframework.web.bind.annotation.RequestBody; // 导入 RequestBody 类
import org.springframework.web.bind.annotation.ResponseBody; // 导入 ResponseBody 类

import javax.servlet.http.HttpServletRequest; // 导入 HttpServletRequest 类
import javax.servlet.http.HttpServletResponse; // 导入 HttpServletResponse 类
import java.io.IOException; // 导入 IOException 类
import java.io.UnsupportedEncodingException; // 导入 UnsupportedEncodingException 类
import java.util.HashMap; // 导入 HashMap 类
import java.util.Iterator; // 导入 Iterator 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 订单相关的接口 // 保留原作者写的块注释
 * @date 2023/2/26 10:09 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Api(value = "订单支付接口", tags = "订单支付接口") // 使用注解 @Api(value = "订单支付接口", tags = "订单支付接口")
@Slf4j // 使用注解 @Slf4j
@Controller // 使用注解 @Controller
public class OrderController { // 定义 class OrderController

    @Autowired // 使用注解 @Autowired
    OrderService orderService; // 执行语句

    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    @ApiOperation("生成支付二维码") // 使用注解 @ApiOperation("生成支付二维码")
    @PostMapping("/generatepaycode") // 使用注解 @PostMapping("/generatepaycode")
    @ResponseBody // 使用注解 @ResponseBody
    public PayRecordDto generatePayCode(@RequestBody AddOrderDto addOrderDto) { // 定义方法 generatePayCode(...)

        SecurityUtil.XcUser user = SecurityUtil.getUser(); // 把 SecurityUtil.getUser() 的返回值赋给 user
        String userId = user.getId(); // 把 user.getId() 的返回值赋给 userId

        //调用service,完成插入订单信息、插入支付记录、生成支付二维码 // 保留原作者写的行内注释
        PayRecordDto payRecordDto = orderService.createOrder(userId, addOrderDto); // 把 orderService.createOrder(userId, addOrderDto) 赋值给 payRecordDto

        return payRecordDto; // 返回 payRecordDto
    } // 代码块结束

    @ApiOperation("扫码下单接口") // 使用注解 @ApiOperation("扫码下单接口")
    @GetMapping("/requestpay") // 使用注解 @GetMapping("/requestpay")
    public void requestpay(String payNo, HttpServletResponse httpResponse) throws IOException, AlipayApiException { // 定义方法 requestpay(...)

        //传入了支付记录号,判断支付记录号是否存在 // 保留原作者写的行内注释
        XcPayRecord payRecordByPayno = orderService.getPayRecordByPayno(payNo); // 把 orderService.getPayRecordByPayno(payNo) 赋值给 payRecordByPayno
        if(payRecordByPayno == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("支付记录不存在"); // 执行语句
        } // 代码块结束
        //支付结果 // 保留原作者写的行内注释
        String status = payRecordByPayno.getStatus(); // 把 payRecordByPayno.getStatus() 的返回值赋给 status
        if ("601002".equals(status)) { // 定义方法 方法(...)

            XueChengPlusException.cast("已支付,无需重复支付"); // 执行语句
        } // 代码块结束

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request // 创建 AlipayTradeWapPayRequest 对象并赋值给 alipayRequest
//        alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp"); // 保留原作者写的行内注释
        alipayRequest.setNotifyUrl("http://tjxt-user-t.itheima.net/xuecheng/orders/paynotify");//在公共参数中设置回跳和通知地址 // 代码逻辑
        alipayRequest.setBizContent("{" + // 代码逻辑
                "    \"out_trade_no\":\""+payNo+"\"," + // 代码逻辑
                "    \"total_amount\":"+payRecordByPayno.getTotalPrice()+"," + // 代码逻辑
                "    \"subject\":\""+payRecordByPayno.getOrderName()+"\"," + // 代码逻辑
                "    \"product_code\":\"QUICK_WAP_WAY\"" + // 代码逻辑
                "  }");//填充业务参数 // 执行语句
        String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK请求支付宝下单 // 把 alipayClient.pageExecute(alipayRequest).getBody() 的返回值赋给 form
        httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET); // 把 " + AlipayConfig.CHARSET) 赋值给 httpResponse.setContentType("text/html;charset
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面 // 执行语句
        httpResponse.getWriter().flush(); // 执行语句


    } // 代码块结束

    @ApiOperation("查询支付结果") // 使用注解 @ApiOperation("查询支付结果")
    @GetMapping("/payresult") // 使用注解 @GetMapping("/payresult")
    @ResponseBody // 使用注解 @ResponseBody
    public PayRecordDto payresult(String payNo) throws IOException { // 定义方法 payresult(...)
        //查询支付结果 // 保留原作者写的行内注释
        PayRecordDto payRecordDto = orderService.queryPayResult(payNo); // 把 orderService.queryPayResult(payNo) 赋值给 payRecordDto
        return payRecordDto; // 返回 payRecordDto

    } // 代码块结束

    //接收支付宝通知 // 保留原作者写的行内注释
    @PostMapping("/paynotify") // 使用注解 @PostMapping("/paynotify")
    public void paynotify(HttpServletRequest request, HttpServletResponse response) throws IOException, AlipayApiException { // 定义方法 paynotify(...)

        //获取支付宝POST过来反馈信息 // 保留原作者写的行内注释
        Map<String,String> params = new HashMap<String,String>(); // 创建 HashMap<String,String> 对象并赋值给 params
        Map requestParams = request.getParameterMap(); // 把 request.getParameterMap() 的返回值赋给 requestParams
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { // 定义方法 方法(...)
            String name = (String) iter.next(); // 把 (String) iter.next() 的返回值赋给 name
            String[] values = (String[]) requestParams.get(name); // 把 (String[]) requestParams.get(name) 赋值给 values
            String valueStr = ""; // 把 "" 赋值给 valueStr
            for (int i = 0; i < values.length; i++) { // 定义方法 方法(...)
                valueStr = (i == values.length - 1) ? valueStr + values[i] // 代码逻辑
                        : valueStr + values[i] + ","; // 执行语句
            } // 代码块结束
            params.put(name, valueStr); // 执行语句
        } // 代码块结束
        boolean verify_result = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2"); // 把 AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2") 赋值给 verify_result

        if(verify_result){//验证成功 // 定义方法 方法(...)
            //商户订单号 // 保留原作者写的行内注释
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 out_trade_no
            //支付宝交易号 // 保留原作者写的行内注释
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_no
            //交易金额 // 保留原作者写的行内注释
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 total_amount
            //交易状态 // 保留原作者写的行内注释
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_status
            if (trade_status.equals("TRADE_SUCCESS")){ // 定义方法 方法(...)
                //更新支付记录表的支付状态为成功,订单表的状态为成功 // 保留原作者写的行内注释
                PayStatusDto payStatusDto = new PayStatusDto(); // 创建 PayStatusDto 对象并赋值给 payStatusDto
                payStatusDto.setTrade_status(trade_status); // 执行语句
                payStatusDto.setTrade_no(trade_no); // 执行语句
                payStatusDto.setOut_trade_no(out_trade_no); // 执行语句
                payStatusDto.setTotal_amount(total_amount); // 执行语句
                payStatusDto.setApp_id(APP_ID); // 执行语句
                orderService.saveAliPayStatus(payStatusDto); // 执行语句
            } // 代码块结束

            response.getWriter().write("success"); // 执行语句

        }else{//验证失败 // 代码逻辑
            response.getWriter().write("fail"); // 执行语句
        } // 代码块结束
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/api/main/com/xuecheng/orders/api/PayTestController.java

package com.xuecheng.orders.api; // 声明类所在的包路径

import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.internal.util.AlipaySignature; // 导入 AlipaySignature 类
import com.alipay.api.request.AlipayTradeWapPayRequest; // 导入 AlipayTradeWapPayRequest 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Controller; // 导入 Controller 类
import org.springframework.web.bind.annotation.PostMapping; // 导入 PostMapping 类
import org.springframework.web.bind.annotation.RequestMapping; // 导入 RequestMapping 类

import javax.servlet.ServletException; // 导入 ServletException 类
import javax.servlet.http.HttpServletRequest; // 导入 HttpServletRequest 类
import javax.servlet.http.HttpServletResponse; // 导入 HttpServletResponse 类
import java.io.IOException; // 导入 IOException 类
import java.io.UnsupportedEncodingException; // 导入 UnsupportedEncodingException 类
import java.util.HashMap; // 导入 HashMap 类
import java.util.Iterator; // 导入 Iterator 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 扫码支付的测试 // 保留原作者写的块注释
 * @date 2023/2/25 16:17 // 保留原作者写的块注释
 */ // 保留原作者写的块注释

@Controller // 使用注解 @Controller
public class PayTestController { // 定义 class PayTestController
    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    //下单接口测试 // 保留原作者写的行内注释
    @RequestMapping("/alipaytest") // 使用注解 @RequestMapping("/alipaytest")
    public void doPost(HttpServletRequest httpRequest, // 代码逻辑
                       HttpServletResponse httpResponse) throws ServletException, IOException, AlipayApiException { // 代码逻辑

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request // 创建 AlipayTradeWapPayRequest 对象并赋值给 alipayRequest
//        alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp"); // 保留原作者写的行内注释
        alipayRequest.setNotifyUrl("http://tjxt-user-t.itheima.net/xuecheng/orders/paynotify");//在公共参数中设置回跳和通知地址 // 代码逻辑
        alipayRequest.setBizContent("{" + // 代码逻辑
                "    \"out_trade_no\":\"202303200101020011\"," + // 代码逻辑
                "    \"total_amount\":0.1," + // 代码逻辑
                "    \"subject\":\"Iphone14 16G\"," + // 代码逻辑
                "    \"product_code\":\"QUICK_WAP_WAY\"" + // 代码逻辑
                "  }");//填充业务参数 // 执行语句
        String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单 // 把 alipayClient.pageExecute(alipayRequest).getBody() 的返回值赋给 form
        httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET); // 把 " + AlipayConfig.CHARSET) 赋值给 httpResponse.setContentType("text/html;charset
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面 // 执行语句
        httpResponse.getWriter().flush(); // 执行语句
    } // 代码块结束

    //支付结果通知 // 保留原作者写的行内注释
    @PostMapping("/paynotifytest") // 使用注解 @PostMapping("/paynotifytest")
    public void paynotify(HttpServletRequest request,HttpServletResponse response) throws IOException, AlipayApiException { // 定义方法 paynotify(...)

        //获取支付宝POST过来反馈信息 // 保留原作者写的行内注释
        Map<String,String> params = new HashMap<String,String>(); // 创建 HashMap<String,String> 对象并赋值给 params
        Map requestParams = request.getParameterMap(); // 把 request.getParameterMap() 的返回值赋给 requestParams
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { // 定义方法 方法(...)
            String name = (String) iter.next(); // 把 (String) iter.next() 的返回值赋给 name
            String[] values = (String[]) requestParams.get(name); // 把 (String[]) requestParams.get(name) 赋值给 values
            String valueStr = ""; // 把 "" 赋值给 valueStr
            for (int i = 0; i < values.length; i++) { // 定义方法 方法(...)
                valueStr = (i == values.length - 1) ? valueStr + values[i] // 代码逻辑
                        : valueStr + values[i] + ","; // 执行语句
            } // 代码块结束
            //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 // 保留原作者写的行内注释
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); // 保留原作者写的行内注释
            params.put(name, valueStr); // 执行语句
        } // 代码块结束
        //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// // 保留原作者写的行内注释

        //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// // 保留原作者写的行内注释
        //计算得出通知验证结果 // 保留原作者写的行内注释
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type) // 保留原作者写的行内注释
        boolean verify_result = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2"); // 把 AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2") 赋值给 verify_result

        if(verify_result){//验证成功 // 定义方法 方法(...)
            ////////////////////////////////////////////////////////////////////////////////////////// // 保留原作者写的行内注释
            //请在这里加上商户的业务逻辑程序代码 // 保留原作者写的行内注释
            //商户订单号 // 保留原作者写的行内注释

            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 out_trade_no
            //支付宝交易号 // 保留原作者写的行内注释

            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_no

            //交易状态 // 保留原作者写的行内注释
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_status


            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— // 保留原作者写的行内注释

            if(trade_status.equals("TRADE_FINISHED")){ // 定义方法 方法(...)
                //判断该笔订单是否在商户网站中已经做过处理 // 保留原作者写的行内注释
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 保留原作者写的行内注释
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 保留原作者写的行内注释
                //如果有做过处理,不执行商户的业务程序 // 保留原作者写的行内注释

                //注意: // 保留原作者写的行内注释
                //如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 // 保留原作者写的行内注释
                //如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。 // 保留原作者写的行内注释
            } else if (trade_status.equals("TRADE_SUCCESS")){ // 定义方法 if(...)
                //判断该笔订单是否在商户网站中已经做过处理 // 保留原作者写的行内注释
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 保留原作者写的行内注释
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 保留原作者写的行内注释
                //如果有做过处理,不执行商户的业务程序 // 保留原作者写的行内注释
                System.out.println(trade_status); // 执行语句
                //注意: // 保留原作者写的行内注释
                //如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。 // 保留原作者写的行内注释
            } // 代码块结束

            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— // 保留原作者写的行内注释
            response.getWriter().write("success"); // 执行语句

            ////////////////////////////////////////////////////////////////////////////////////////// // 保留原作者写的行内注释
        }else{//验证失败 // 代码逻辑
            response.getWriter().write("fail"); // 执行语句
        } // 代码块结束


    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-orders/api/main/com/xuecheng/orders/config/ResouceServerConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; // 导入 EnableGlobalMethodSecurity 类
import org.springframework.security.config.annotation.web.builders.HttpSecurity; // 导入 HttpSecurity 类
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; // 导入 EnableResourceServer 类
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; // 导入 ResourceServerConfigurerAdapter 类
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; // 导入 ResourceServerSecurityConfigurer 类
import org.springframework.security.oauth2.provider.token.TokenStore; // 导入 TokenStore 类

/** // 保留原作者写的块注释
 * @author Administrator // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 **/ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
@EnableResourceServer // 使用注解 @EnableResourceServer
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) // 使用注解 @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class ResouceServerConfig extends ResourceServerConfigurerAdapter { // 定义 class ResouceServerConfig


    //资源服务标识 // 保留原作者写的行内注释
    public static final String RESOURCE_ID = "xuecheng-plus"; // 把 "xuecheng-plus" 赋值给 RESOURCE_ID

    @Autowired // 使用注解 @Autowired
    TokenStore tokenStore; // 执行语句

    @Override // 使用注解 @Override
    public void configure(ResourceServerSecurityConfigurer resources) { // 定义方法 configure(...)
        resources.resourceId(RESOURCE_ID)//资源 id // 代码逻辑
                .tokenStore(tokenStore) // 代码逻辑
                .stateless(true); // 执行语句
    } // 代码块结束

    @Override // 使用注解 @Override
    public void configure(HttpSecurity http) throws Exception { // 定义方法 configure(...)
        http.csrf().disable() // 代码逻辑
                .authorizeRequests() // 代码逻辑
//                .antMatchers("/r/**","/course/**").authenticated()//所有/r/**的请求必须认证通过 // 保留原作者写的行内注释
                .anyRequest().permitAll() // 代码逻辑
        ; // 执行语句
    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-orders/api/main/com/xuecheng/orders/config/TokenConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类
import org.springframework.security.oauth2.provider.token.TokenStore; // 导入 TokenStore 类
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; // 导入 JwtAccessTokenConverter 类
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; // 导入 JwtTokenStore 类

/** // 保留原作者写的块注释
 * @author Administrator // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 **/ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class TokenConfig { // 定义 class TokenConfig

    //jwt签名密钥,与认证服务保持一致 // 保留原作者写的行内注释
    private String SIGNING_KEY = "mq123"; // 把 "mq123" 赋值给 SIGNING_KEY

    @Bean // 使用注解 @Bean
    public TokenStore tokenStore() { // 定义方法 tokenStore(...)
        //JWT令牌存储方案 // 保留原作者写的行内注释
        return new JwtTokenStore(accessTokenConverter()); // 返回 new JwtTokenStore(accessTokenConverter())
    } // 代码块结束

    @Bean // 使用注解 @Bean
    public JwtAccessTokenConverter accessTokenConverter() { // 定义方法 accessTokenConverter(...)
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); // 创建 JwtAccessTokenConverter 对象并赋值给 converter
        converter.setSigningKey(SIGNING_KEY); // 执行语句
        return converter; // 返回 converter
    } // 代码块结束

   /* @Bean // 保留原作者写的块注释
    public TokenStore tokenStore() { // 定义方法 tokenStore(...)
        //使用内存存储令牌(普通令牌) // 保留原作者写的行内注释
        return new InMemoryTokenStore(); // 返回 new InMemoryTokenStore()
    }*/ // 代码逻辑
} // 代码块结束

文件:xuecheng-plus-orders/api/main/com/xuecheng/orders/util/SecurityUtil.java

package com.xuecheng.orders.util; // 声明类所在的包路径

import com.alibaba.fastjson.JSON; // 导入 JSON 类
import lombok.Data; // 导入 Data 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.security.core.context.SecurityContextHolder; // 导入 SecurityContextHolder 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/*** // 保留原作者写的块注释
 * 获取当前登录用户信息,使用解析jwt中的用户信息 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
public class SecurityUtil { // 定义 class SecurityUtil

    public static XcUser getUser() { // 定义方法 getUser(...)
        try { // 尝试执行可能抛出异常的代码
            Object principalObj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // 把 SecurityContextHolder.getContext().getAuthentication().getPrincipal() 的返回值赋给 principalObj
            if (principalObj instanceof String) { // 定义方法 方法(...)
                //取出用户身份信息 // 保留原作者写的行内注释
                String principal = principalObj.toString(); // 把 principalObj.toString() 的返回值赋给 principal
                //将json转成对象 // 保留原作者写的行内注释
                XcUser user = JSON.parseObject(principal, XcUser.class); // 把 JSON.parseObject(principal, XcUser.class) 赋值给 user
                return user; // 返回 user
            } // 代码块结束
        } catch (Exception e) { // 定义方法 catch(...)
            log.error("获取当前登录用户身份出错:{}", e.getMessage()); // 执行语句
            e.printStackTrace(); // 执行语句
        } // 代码块结束

        return null; // 返回 null
    } // 代码块结束

    @Data // 使用注解 @Data
    public static class XcUser implements Serializable { // 代码逻辑

        private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

        private String id; // 执行语句

        private String username; // 执行语句

        private String password; // 执行语句

        private String salt; // 执行语句

        private String name; // 执行语句
        private String nickname; // 执行语句
        private String wxUnionid; // 执行语句
        private String companyId; // 执行语句
        /** // 保留原作者写的块注释
         * 头像 // 保留原作者写的块注释
         */ // 保留原作者写的块注释
        private String userpic; // 执行语句

        private String utype; // 执行语句

        private LocalDateTime birthday; // 执行语句

        private String sex; // 执行语句

        private String email; // 执行语句

        private String cellphone; // 执行语句

        private String qq; // 执行语句

        /** // 保留原作者写的块注释
         * 用户状态 // 保留原作者写的块注释
         */ // 保留原作者写的块注释
        private String status; // 执行语句

        private LocalDateTime createTime; // 执行语句

        private LocalDateTime updateTime; // 执行语句


    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-orders/api/main/com/xuecheng/OrdersApiApplication.java

package com.xuecheng; // 声明类所在的包路径

import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类

@SpringBootApplication // 使用注解 @SpringBootApplication
public class OrdersApiApplication { // 定义 class OrdersApiApplication

    public static void main(String[] args) { // 定义方法 main(...)
        SpringApplication.run(OrdersApiApplication.class, args); // 执行语句
    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-orders/api/resources/bootstrap.yml

#微服务配置
spring:
  application:
    name: orders-api
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        extension-configs:
          - data-id: orders-service-${spring.profiles.active}.yaml
            group: xuecheng-plus-project
            refresh: true
        shared-configs:
          - data-id: swagger-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: rabbitmq-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true

  profiles:
    active: dev

文件:xuecheng-plus-orders/api/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="180" packages="">
    <properties>
        <property name="logdir">logs</property>
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${PATTERN}"/>
        </Console>

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log"
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true">
            <PatternLayout pattern="${PATTERN}"/>
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log"
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true">
            <PatternLayout pattern="${PATTERN}"/>
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true">
            <AppenderRef ref="ErrorAppender"/>
            <AppenderRef ref="DebugAppender"/>
        </Async>
    </Appenders>
    
    <Loggers>
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO">
        </logger>
        <logger name="org.mybatis" level="INFO">
        </logger>
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG">
        </logger>

        <logger name="springfox" level="INFO">
        </logger>
		<logger name="org.apache.http" level="INFO">
        </logger>
        <logger name="com.netflix.discovery" level="INFO">
        </logger>
        
        <logger name="RocketmqCommon"  level="INFO" >
		</logger>
		
		<logger name="RocketmqRemoting" level="INFO"  >
		</logger>
		
		<logger name="RocketmqClient" level="WARN">
		</logger>

        <logger name="org.dromara.hmily" level="WARN">
        </logger>

        <logger name="org.dromara.hmily.lottery" level="WARN">
        </logger>

        <logger name="org.dromara.hmily.bonuspoint" level="WARN">
        </logger>
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true">
            <AppenderRef ref="AsyncAppender"/>
            <AppenderRef ref="Console"/>
            <AppenderRef ref="DebugAppender"/>
        </Root>
    </Loggers>
</Configuration>

文件:xuecheng-plus-orders/api_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-orders</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>xuecheng-plus-orders-api</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-orders-model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-orders-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!--cloud的基础环境包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
        </dependency>

        <!-- Spring Boot 的 Spring Web MVC 集成 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Boot 集成 Junit -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Spring Boot 集成 log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <!-- Spring Boot 集成 swagger -->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
        </dependency>


        <!--认证相关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.3</version>
        </dependency>
    </dependencies>

</project>

文件:xuecheng-plus-orders/model/com/xuecheng/orders/model/dto/AddOrderDto.java

package com.xuecheng.orders.model.dto; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 创建商品订单 // 保留原作者写的块注释
 * @date 2022/10/4 10:21 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class AddOrderDto  { // 定义 class AddOrderDto

    /** // 保留原作者写的块注释
     * 总价 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float totalPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 订单类型 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderType; // 执行语句

    /** // 保留原作者写的块注释
     * 订单名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderName; // 执行语句
    /** // 保留原作者写的块注释
     * 订单描述 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDescrip; // 执行语句

    /** // 保留原作者写的块注释
     * 订单明细json,不可为空 // 保留原作者写的块注释
     * [{"goodsId":"","goodsType":"","goodsName":"","goodsPrice":"","goodsDetail":""},{...}] // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDetail; // 执行语句

    /** // 保留原作者写的块注释
     * 外部系统业务id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outBusinessId; // 执行语句

} // 代码块结束

文件:xuecheng-plus-orders/model/com/xuecheng/orders/model/dto/PayRecordDto.java

package com.xuecheng.orders.model.dto; // 声明类所在的包路径

import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 支付记录dto // 保留原作者写的块注释
 * @date 2022/10/4 11:30 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class PayRecordDto extends XcPayRecord { // 定义 class PayRecordDto

    //二维码 // 保留原作者写的行内注释
    private String qrcode; // 执行语句

} // 代码块结束

文件:xuecheng-plus-orders/model/com/xuecheng/orders/model/dto/PayStatusDto.java

package com.xuecheng.orders.model.dto; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 支付结果数据, 用于接收支付结果通知处理逻辑 // 保留原作者写的块注释
 * @date 2022/10/4 16:49 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class PayStatusDto { // 定义 class PayStatusDto

    //商户订单号 // 保留原作者写的行内注释
    String out_trade_no; // 执行语句
    //支付宝交易号 // 保留原作者写的行内注释
    String trade_no; // 执行语句
    //交易状态 // 保留原作者写的行内注释
    String trade_status; // 执行语句
    //appid // 保留原作者写的行内注释
    String app_id; // 执行语句
    //total_amount // 保留原作者写的行内注释
    String total_amount; // 执行语句
} // 代码块结束

文件:xuecheng-plus-orders/model/com/xuecheng/orders/model/po/XcOrders.java

package com.xuecheng.orders.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.FieldFill; // 导入 FieldFill 类
import com.baomidou.mybatisplus.annotation.TableField; // 导入 TableField 类
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("xc_orders") // 使用注解 @TableName("xc_orders")
public class XcOrders implements Serializable { // 定义 class XcOrders

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 订单号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 总价 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float totalPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 创建时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 交易状态 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 用户id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String userId; // 执行语句


    /** // 保留原作者写的块注释
     * 订单类型 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderType; // 执行语句

    /** // 保留原作者写的块注释
     * 订单名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderName; // 执行语句

    /** // 保留原作者写的块注释
     * 订单描述 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDescrip; // 执行语句

    /** // 保留原作者写的块注释
     * 订单明细json // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDetail; // 执行语句

    /** // 保留原作者写的块注释
     * 外部系统业务id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outBusinessId; // 执行语句


} // 代码块结束

文件:xuecheng-plus-orders/model/com/xuecheng/orders/model/po/XcOrdersGoods.java

package com.xuecheng.orders.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.IdType; // 导入 IdType 类
import com.baomidou.mybatisplus.annotation.TableId; // 导入 TableId 类
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("xc_orders_goods") // 使用注解 @TableName("xc_orders_goods")
public class XcOrdersGoods implements Serializable { // 定义 class XcOrdersGoods

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    @TableId(value = "id", type = IdType.AUTO) // 使用注解 @TableId(value = "id", type = IdType.AUTO)
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 订单号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long orderId; // 执行语句

    /** // 保留原作者写的块注释
     * 商品id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsId; // 执行语句

    /** // 保留原作者写的块注释
     * 商品类型 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsType; // 执行语句

    /** // 保留原作者写的块注释
     * 商品名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsName; // 执行语句

    /** // 保留原作者写的块注释
     * 商品交易价,单位分 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float goodsPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 商品详情json,可为空 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsDetail; // 执行语句


} // 代码块结束

文件:xuecheng-plus-orders/model/com/xuecheng/orders/model/po/XcPayRecord.java

package com.xuecheng.orders.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.FieldFill; // 导入 FieldFill 类
import com.baomidou.mybatisplus.annotation.TableField; // 导入 TableField 类
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("xc_pay_record") // 使用注解 @TableName("xc_pay_record")
public class XcPayRecord implements Serializable { // 定义 class XcPayRecord

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 支付记录号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 本系统支付交易号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long payNo; // 执行语句

    /** // 保留原作者写的块注释
     * 第三方支付交易流水号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outPayNo; // 执行语句

    /** // 保留原作者写的块注释
     * 第三方支付渠道编号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outPayChannel; // 执行语句

    /** // 保留原作者写的块注释
     * 商品订单号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long orderId; // 执行语句

    /** // 保留原作者写的块注释
     * 订单名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderName; // 执行语句
    /** // 保留原作者写的块注释
     * 订单总价单位元 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float totalPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 币种CNY // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String currency; // 执行语句

    /** // 保留原作者写的块注释
     * 创建时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 支付状态 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 支付成功时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime paySuccessTime; // 执行语句

    /** // 保留原作者写的块注释
     * 用户id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String userId; // 执行语句



} // 代码块结束

文件:xuecheng-plus-orders/model_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-orders</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>xuecheng-plus-orders-model</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-base</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!--存在mybatisplus注解添加相关注解保证不报错-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

文件:xuecheng-plus-orders/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-parent</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        <relativePath>../xuecheng-plus-parent</relativePath> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-orders</artifactId> <!-- SQL 语句片段 -->
    <packaging>pom</packaging> <!-- SQL 语句片段 -->
    <modules> <!-- SQL 语句片段 -->
        <module>xuecheng-plus-orders-api</module> <!-- SQL 语句片段 -->
        <module>xuecheng-plus-orders-service</module> <!-- SQL 语句片段 -->
        <module>xuecheng-plus-orders-model</module> <!-- SQL 语句片段 -->
    </modules> <!-- SQL 语句片段 -->


</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-orders/root_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-parent</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../xuecheng-plus-parent</relativePath>
    </parent>
    <artifactId>xuecheng-plus-orders</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>xuecheng-plus-orders-api</module>
        <module>xuecheng-plus-orders-service</module>
        <module>xuecheng-plus-orders-model</module>
    </modules>


</project>

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/config/AlipayConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径
 /** // 保留原作者写的块注释
 * @description 支付宝配置参数 // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/10/20 22:45 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 public class AlipayConfig { // 定义 class AlipayConfig
  // 商户appid // 保留原作者写的行内注释
//	public static String APPID = ""; // 保留原作者写的行内注释
  // 私钥 pkcs8格式的 // 保留原作者写的行内注释
//	public static String RSA_PRIVATE_KEY = ""; // 保留原作者写的行内注释
  // 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 // 保留原作者写的行内注释
  public static String notify_url = "http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/notify_url.jsp"; // 代码逻辑
  // 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址 // 保留原作者写的行内注释
  public static String return_url = "http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/return_url.jsp"; // 代码逻辑
  // 请求网关地址 // 保留原作者写的行内注释
  public static String URL = "https://openapi.alipaydev.com/gateway.do"; // 代码逻辑
  // 编码 // 保留原作者写的行内注释
  public static String CHARSET = "UTF-8"; // 把 "UTF-8" 赋值给 CHARSET
  // 返回格式 // 保留原作者写的行内注释
  public static String FORMAT = "json"; // 把 "json" 赋值给 FORMAT
  // 支付宝公钥 // 保留原作者写的行内注释
//	public static String ALIPAY_PUBLIC_KEY = ""; // 保留原作者写的行内注释
  // 日志记录目录 // 保留原作者写的行内注释
  public static String log_path = "/log"; // 把 "/log" 赋值给 log_path
  // RSA2 // 保留原作者写的行内注释
  public static String SIGNTYPE = "RSA2"; // 把 "RSA2" 赋值给 SIGNTYPE
 } // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/config/MybatisPlusConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.DbType; // 导入 DbType 类
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; // 导入 MybatisPlusInterceptor 类
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; // 导入 PaginationInnerInterceptor 类
import org.mybatis.spring.annotation.MapperScan; // 导入 MapperScan 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * <P> // 保留原作者写的块注释
 * 		Mybatis-Plus 配置 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
@MapperScan("com.xuecheng.orders.mapper") // 使用注解 @MapperScan("com.xuecheng.orders.mapper")
public class MybatisPlusConfig { // 定义 class MybatisPlusConfig
	/** // 保留原作者写的块注释
	 * 新的分页插件 // 保留原作者写的块注释
	 * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false // 保留原作者写的块注释
	 * 避免缓存出现问题(该属性会在旧插件移除后一同移除) // 保留原作者写的块注释
	 */ // 保留原作者写的块注释
	@Bean // 使用注解 @Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() { // 定义方法 mybatisPlusInterceptor(...)
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建 MybatisPlusInterceptor 对象并赋值给 interceptor
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 执行语句
		return interceptor; // 返回 interceptor
	} // 代码块结束


} // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/config/PayNotifyConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import com.alibaba.fastjson.JSON; // 导入 JSON 类
import com.xuecheng.messagesdk.model.po.MqMessage; // 导入 MqMessage 类
import com.xuecheng.messagesdk.service.MqMessageService; // 导入 MqMessageService 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.amqp.core.*; // 导入 * 类
import org.springframework.amqp.rabbit.core.RabbitTemplate; // 导入 RabbitTemplate 类
import org.springframework.beans.BeansException; // 导入 BeansException 类
import org.springframework.beans.factory.annotation.Qualifier; // 导入 Qualifier 类
import org.springframework.context.ApplicationContext; // 导入 ApplicationContext 类
import org.springframework.context.ApplicationContextAware; // 导入 ApplicationContextAware 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/23 16:59 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Configuration // 使用注解 @Configuration
public class PayNotifyConfig implements ApplicationContextAware { // 定义 class PayNotifyConfig

    //交换机 // 保留原作者写的行内注释
    public static final String PAYNOTIFY_EXCHANGE_FANOUT = "paynotify_exchange_fanout"; // 把 "paynotify_exchange_fanout" 赋值给 PAYNOTIFY_EXCHANGE_FANOUT
    //支付结果通知消息类型 // 保留原作者写的行内注释
    public static final String MESSAGE_TYPE = "payresult_notify"; // 把 "payresult_notify" 赋值给 MESSAGE_TYPE
    //支付通知队列 // 保留原作者写的行内注释
    public static final String PAYNOTIFY_QUEUE = "paynotify_queue"; // 把 "paynotify_queue" 赋值给 PAYNOTIFY_QUEUE

    //声明交换机,且持久化 // 保留原作者写的行内注释
    @Bean(PAYNOTIFY_EXCHANGE_FANOUT) // 使用注解 @Bean(PAYNOTIFY_EXCHANGE_FANOUT)
    public FanoutExchange paynotify_exchange_fanout() { // 定义方法 paynotify_exchange_fanout(...)
        // 三个参数:交换机名称、是否持久化、当没有queue与其绑定时是否自动删除 // 保留原作者写的行内注释
        return new FanoutExchange(PAYNOTIFY_EXCHANGE_FANOUT, true, false); // 返回 new FanoutExchange(PAYNOTIFY_EXCHANGE_FANOUT, true, false)
    } // 代码块结束
    //支付通知队列,且持久化 // 保留原作者写的行内注释
    @Bean(PAYNOTIFY_QUEUE) // 使用注解 @Bean(PAYNOTIFY_QUEUE)
    public Queue course_publish_queue() { // 定义方法 course_publish_queue(...)
        return QueueBuilder.durable(PAYNOTIFY_QUEUE).build(); // 返回 QueueBuilder.durable(PAYNOTIFY_QUEUE).build()
    } // 代码块结束

    //交换机和支付通知队列绑定 // 保留原作者写的行内注释
    @Bean // 使用注解 @Bean
    public Binding binding_course_publish_queue(@Qualifier(PAYNOTIFY_QUEUE) Queue queue, @Qualifier(PAYNOTIFY_EXCHANGE_FANOUT) FanoutExchange exchange) { // 定义方法 binding_course_publish_queue(...)
        return BindingBuilder.bind(queue).to(exchange); // 返回 BindingBuilder.bind(queue).to(exchange)
    } // 代码块结束

    @Override // 使用注解 @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 定义方法 setApplicationContext(...)
        // 获取RabbitTemplate // 保留原作者写的行内注释
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class); // 把 applicationContext.getBean(RabbitTemplate.class) 赋值给 rabbitTemplate
        //消息处理service // 保留原作者写的行内注释
        MqMessageService mqMessageService = applicationContext.getBean(MqMessageService.class); // 把 applicationContext.getBean(MqMessageService.class) 赋值给 mqMessageService
        // 设置ReturnCallback // 保留原作者写的行内注释
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> { // 定义方法 方法(...)
            // 投递失败,记录日志 // 保留原作者写的行内注释
            log.info("消息发送失败,应答码{},原因{},交换机{},路由键{},消息{}", // 代码逻辑
                    replyCode, replyText, exchange, routingKey, message.toString()); // 执行语句
            MqMessage mqMessage = JSON.parseObject(message.toString(), MqMessage.class); // 把 JSON.parseObject(message.toString(), MqMessage.class) 赋值给 mqMessage
            //将消息再添加到消息表 // 保留原作者写的行内注释
            mqMessageService.addMessage(mqMessage.getMessageType(),mqMessage.getBusinessKey1(),mqMessage.getBusinessKey2(),mqMessage.getBusinessKey3()); // 执行语句

        }); // 执行语句
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/mapper/XcOrdersGoodsMapper.java

package com.xuecheng.orders.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.orders.model.po.XcOrdersGoods; // 导入 XcOrdersGoods 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface XcOrdersGoodsMapper extends BaseMapper<XcOrdersGoods> { // 定义 interface XcOrdersGoodsMapper

} // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/mapper/XcOrdersGoodsMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.orders.mapper.XcOrdersGoodsMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.orders.model.po.XcOrdersGoods"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="order_id" property="orderId" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_id" property="goodsId" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_type" property="goodsType" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_name" property="goodsName" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_price" property="goodsPrice" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_detail" property="goodsDetail" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, order_id, goods_id, goods_type, goods_name, goods_price, goods_detail <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/mapper/XcOrdersMapper.java

package com.xuecheng.orders.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.orders.model.po.XcOrders; // 导入 XcOrders 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface XcOrdersMapper extends BaseMapper<XcOrders> { // 定义 interface XcOrdersMapper

} // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/mapper/XcOrdersMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.orders.mapper.XcOrdersMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.orders.model.po.XcOrders"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="total_price" property="totalPrice" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="user_id" property="userId" /> <!-- 字段与属性的映射规则 -->
        <result column="company_id" property="companyId" /> <!-- 字段与属性的映射规则 -->
        <result column="order_type" property="orderType" /> <!-- 字段与属性的映射规则 -->
        <result column="order_descrip" property="orderDescrip" /> <!-- 字段与属性的映射规则 -->
        <result column="order_detail" property="orderDetail" /> <!-- 字段与属性的映射规则 -->
        <result column="out_order_id" property="outOrderId" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, total_price, create_date, status, user_id, company_id, order_type, order_descrip, order_detail, out_order_id <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/mapper/XcPayRecordMapper.java

package com.xuecheng.orders.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface XcPayRecordMapper extends BaseMapper<XcPayRecord> { // 定义 interface XcPayRecordMapper

} // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/mapper/XcPayRecordMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.orders.mapper.XcPayRecordMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.orders.model.po.XcPayRecord"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="pay_no" property="payNo" /> <!-- 字段与属性的映射规则 -->
        <result column="out_pay_no" property="outPayNo" /> <!-- 字段与属性的映射规则 -->
        <result column="out_pay_channel" property="outPayChannel" /> <!-- 字段与属性的映射规则 -->
        <result column="order_id" property="orderId" /> <!-- 字段与属性的映射规则 -->
        <result column="order_name" property="orderName" /> <!-- 字段与属性的映射规则 -->
        <result column="total_price" property="totalPrice" /> <!-- 字段与属性的映射规则 -->
        <result column="currency" property="currency" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="pay_success_time" property="paySuccessTime" /> <!-- 字段与属性的映射规则 -->
        <result column="user_id" property="userId" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, pay_no, out_pay_no, out_pay_channel, order_id,order_name, total_price, currency, create_date, status, pay_success_time, user_id <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/service/impl/OrderServiceImpl.java

package com.xuecheng.orders.service.impl; // 声明类所在的包路径

import com.alibaba.fastjson.JSON; // 导入 JSON 类
import com.alibaba.fastjson.JSONObject; // 导入 JSONObject 类
import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.request.AlipayTradeQueryRequest; // 导入 AlipayTradeQueryRequest 类
import com.alipay.api.response.AlipayTradeQueryResponse; // 导入 AlipayTradeQueryResponse 类
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 导入 LambdaQueryWrapper 类
import com.xuecheng.base.exception.XueChengPlusException; // 导入 XueChengPlusException 类
import com.xuecheng.base.utils.IdWorkerUtils; // 导入 IdWorkerUtils 类
import com.xuecheng.base.utils.QRCodeUtil; // 导入 QRCodeUtil 类
import com.xuecheng.messagesdk.model.po.MqMessage; // 导入 MqMessage 类
import com.xuecheng.messagesdk.service.MqMessageService; // 导入 MqMessageService 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import com.xuecheng.orders.config.PayNotifyConfig; // 导入 PayNotifyConfig 类
import com.xuecheng.orders.mapper.XcOrdersGoodsMapper; // 导入 XcOrdersGoodsMapper 类
import com.xuecheng.orders.mapper.XcOrdersMapper; // 导入 XcOrdersMapper 类
import com.xuecheng.orders.mapper.XcPayRecordMapper; // 导入 XcPayRecordMapper 类
import com.xuecheng.orders.model.dto.AddOrderDto; // 导入 AddOrderDto 类
import com.xuecheng.orders.model.dto.PayRecordDto; // 导入 PayRecordDto 类
import com.xuecheng.orders.model.dto.PayStatusDto; // 导入 PayStatusDto 类
import com.xuecheng.orders.model.po.XcOrders; // 导入 XcOrders 类
import com.xuecheng.orders.model.po.XcOrdersGoods; // 导入 XcOrdersGoods 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类
import com.xuecheng.orders.service.OrderService; // 导入 OrderService 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.amqp.core.Message; // 导入 Message 类
import org.springframework.amqp.core.MessageBuilder; // 导入 MessageBuilder 类
import org.springframework.amqp.core.MessageDeliveryMode; // 导入 MessageDeliveryMode 类
import org.springframework.amqp.rabbit.connection.CorrelationData; // 导入 CorrelationData 类
import org.springframework.amqp.rabbit.core.RabbitTemplate; // 导入 RabbitTemplate 类
import org.springframework.beans.BeanUtils; // 导入 BeanUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Service; // 导入 Service 类
import org.springframework.transaction.annotation.Transactional; // 导入 Transactional 类

import java.io.IOException; // 导入 IOException 类
import java.nio.charset.StandardCharsets; // 导入 StandardCharsets 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类
import java.util.List; // 导入 List 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 订单相关的接口 // 保留原作者写的块注释
 * @date 2023/2/26 10:12 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Service // 使用注解 @Service
public class OrderServiceImpl implements OrderService { // 定义 class OrderServiceImpl

    @Autowired // 使用注解 @Autowired
    XcOrdersMapper ordersMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    XcOrdersGoodsMapper ordersGoodsMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    MqMessageService mqMessageService; // 执行语句

    @Autowired // 使用注解 @Autowired
    XcPayRecordMapper payRecordMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    RabbitTemplate rabbitTemplate; // 执行语句

    @Autowired // 使用注解 @Autowired
    OrderServiceImpl currentProxy; // 执行语句

    @Value("${pay.qrcodeurl}") // 使用注解 @Value("${pay.qrcodeurl}")
    String qrcodeurl; // 执行语句

    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    @Transactional // 使用注解 @Transactional
    @Override // 使用注解 @Override
    public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto) { // 定义方法 createOrder(...)

        //插入订单表,订单主表,订单明细表 // 保留原作者写的行内注释
        XcOrders xcOrders = saveXcOrders(userId, addOrderDto); // 把 saveXcOrders(userId, addOrderDto) 赋值给 xcOrders

        //插入支付记录 // 保留原作者写的行内注释
        XcPayRecord payRecord = createPayRecord(xcOrders); // 把 createPayRecord(xcOrders) 赋值给 payRecord
        Long payNo = payRecord.getPayNo(); // 把 payRecord.getPayNo() 的返回值赋给 payNo

        //生成二维码 // 保留原作者写的行内注释
        QRCodeUtil qrCodeUtil = new QRCodeUtil(); // 创建 QRCodeUtil 对象并赋值给 qrCodeUtil
        //支付二维码的url // 保留原作者写的行内注释
        String url = String.format(qrcodeurl, payNo); // 把 String.format(qrcodeurl, payNo) 赋值给 url
        //二维码图片 // 保留原作者写的行内注释
        String qrCode = null; // 把变量 qrCode 初始化为 null
        try { // 尝试执行可能抛出异常的代码
            qrCode = qrCodeUtil.createQRCode(url, 200, 200); // 把 qrCodeUtil.createQRCode(url, 200, 200) 赋值给 qrCode
        } catch (IOException e) { // 定义方法 catch(...)
            XueChengPlusException.cast("生成二维码出错"); // 执行语句
        } // 代码块结束

        PayRecordDto payRecordDto = new PayRecordDto(); // 创建 PayRecordDto 对象并赋值给 payRecordDto
        BeanUtils.copyProperties(payRecord,payRecordDto); // 执行语句
        payRecordDto.setQrcode(qrCode); // 执行语句

        return payRecordDto; // 返回 payRecordDto
    } // 代码块结束

    @Override // 使用注解 @Override
    public XcPayRecord getPayRecordByPayno(String payNo) { // 定义方法 getPayRecordByPayno(...)
        XcPayRecord xcPayRecord = payRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo)); // 把 payRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo)) 赋值给 xcPayRecord
        return xcPayRecord; // 返回 xcPayRecord
    } // 代码块结束

    @Override // 使用注解 @Override
    public PayRecordDto queryPayResult(String payNo) { // 定义方法 queryPayResult(...)

        //调用支付宝的接口查询支付结果 // 保留原作者写的行内注释
        PayStatusDto payStatusDto = queryPayResultFromAlipay(payNo); // 把 queryPayResultFromAlipay(payNo) 赋值给 payStatusDto

        System.out.println(payStatusDto); // 执行语句
        //拿到支付结果更新支付记录表和订单表的支付状态 // 保留原作者写的行内注释
        currentProxy.saveAliPayStatus(payStatusDto); // 执行语句
        //要返回最新的支付记录信息 // 保留原作者写的行内注释
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNo); // 把 getPayRecordByPayno(payNo) 赋值给 payRecordByPayno
        PayRecordDto payRecordDto = new PayRecordDto(); // 创建 PayRecordDto 对象并赋值给 payRecordDto
        BeanUtils.copyProperties(payRecordByPayno,payRecordDto); // 执行语句

        return payRecordDto; // 返回 payRecordDto
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 请求支付宝查询支付结果 // 保留原作者写的块注释
     * @param payNo 支付交易号 // 保留原作者写的块注释
     * @return 支付结果 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public PayStatusDto queryPayResultFromAlipay(String payNo){ // 定义方法 queryPayResultFromAlipay(...)

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); // 创建 AlipayTradeQueryRequest 对象并赋值给 request
        JSONObject bizContent = new JSONObject(); // 创建 JSONObject 对象并赋值给 bizContent
        bizContent.put("out_trade_no", payNo); // 执行语句
        //bizContent.put("trade_no", "2014112611001004680073956707"); // 保留原作者写的行内注释
        request.setBizContent(bizContent.toString()); // 执行语句
        //支付宝返回的信息 // 保留原作者写的行内注释
        String body = null; // 把变量 body 初始化为 null
        try { // 尝试执行可能抛出异常的代码
            AlipayTradeQueryResponse response = alipayClient.execute ( request ); //通过alipayClient调用API,获得对应的response类 // 把 alipayClient.execute ( request ) 赋值给 response
            if(!response.isSuccess()){//交易不成功 // 定义方法 方法(...)
                XueChengPlusException.cast("请求支付宝查询支付结果失败"); // 执行语句
            } // 代码块结束
            body = response.getBody(); // 把 response.getBody() 的返回值赋给 body
        } catch (AlipayApiException e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
           XueChengPlusException.cast("请求支付查询支付结果异常"); // 执行语句
        } // 代码块结束
        Map bodyMap = JSON.parseObject(body, Map.class); // 把 JSON.parseObject(body, Map.class) 赋值给 bodyMap
        Map alipay_trade_query_response = (Map) bodyMap.get("alipay_trade_query_response"); // 把 (Map) bodyMap.get("alipay_trade_query_response") 赋值给 alipay_trade_query_response

        //解析支付结果 // 保留原作者写的行内注释
        String trade_no = (String) alipay_trade_query_response.get("trade_no"); // 把 (String) alipay_trade_query_response.get("trade_no") 赋值给 trade_no
        String trade_status = (String) alipay_trade_query_response.get("trade_status"); // 把 (String) alipay_trade_query_response.get("trade_status") 赋值给 trade_status
        String total_amount = (String) alipay_trade_query_response.get("total_amount"); // 把 (String) alipay_trade_query_response.get("total_amount") 赋值给 total_amount
        PayStatusDto payStatusDto = new PayStatusDto(); // 创建 PayStatusDto 对象并赋值给 payStatusDto
        payStatusDto.setOut_trade_no(payNo); // 执行语句
        payStatusDto.setTrade_no(trade_no);//支付宝的交易号 // 执行语句
        payStatusDto.setTrade_status(trade_status);//交易状态 // 执行语句
        payStatusDto.setApp_id(APP_ID); // 执行语句
        payStatusDto.setTotal_amount(total_amount);//总金额 // 执行语句


        return payStatusDto; // 返回 payStatusDto
    } // 代码块结束

    /** // 保留原作者写的块注释
     * @description 保存支付宝支付结果 // 保留原作者写的块注释
     * @param payStatusDto  支付结果信息 从支付宝查询到的信息 // 保留原作者写的块注释
     * @return void // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/10/4 16:52 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @Transactional // 使用注解 @Transactional
    public void saveAliPayStatus(PayStatusDto payStatusDto){ // 定义方法 saveAliPayStatus(...)
        //支付记录号 // 保留原作者写的行内注释
        String payNO = payStatusDto.getOut_trade_no(); // 把 payStatusDto.getOut_trade_no() 的返回值赋给 payNO
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNO); // 把 getPayRecordByPayno(payNO) 赋值给 payRecordByPayno
        if(payRecordByPayno == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("找不到相关的支付记录"); // 执行语句
        } // 代码块结束
        //拿到相关联的订单id // 保留原作者写的行内注释
        Long orderId = payRecordByPayno.getOrderId(); // 把 payRecordByPayno.getOrderId() 的返回值赋给 orderId
        XcOrders xcOrders = ordersMapper.selectById(orderId); // 把 ordersMapper.selectById(orderId) 赋值给 xcOrders
        if(xcOrders == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("找不到相关联的订单"); // 执行语句
        } // 代码块结束
        //支付状态 // 保留原作者写的行内注释
        String statusFromDb = payRecordByPayno.getStatus(); // 把 payRecordByPayno.getStatus() 的返回值赋给 statusFromDb
        //如果数据库支付的状态已经是成功了,不再处理了 // 保留原作者写的行内注释
        if("601002".equals(statusFromDb)){ // 定义方法 方法(...)
            return ; // 返回 
        } // 代码块结束

        //如果支付成功 // 保留原作者写的行内注释
        String trade_status = payStatusDto.getTrade_status();//从支付宝查询到的支付结果 // 把 payStatusDto.getTrade_status() 的返回值赋给 trade_status
        if(trade_status.equals("TRADE_SUCCESS")){//支付宝返回的信息为支付成功 // 定义方法 方法(...)
            //更新支付记录表的状态为支付成功 // 保留原作者写的行内注释
            payRecordByPayno.setStatus("601002"); // 执行语句
            //支付宝的订单号 // 保留原作者写的行内注释
            payRecordByPayno.setOutPayNo(payStatusDto.getTrade_no()); // 执行语句
            //第三方支付渠道编号 // 保留原作者写的行内注释
            payRecordByPayno.setOutPayChannel("Alipay"); // 执行语句
            //支付成功时间 // 保留原作者写的行内注释
            payRecordByPayno.setPaySuccessTime(LocalDateTime.now()); // 执行语句
            payRecordMapper.updateById(payRecordByPayno); // 执行语句

            //更新订单表的状态为支付成功 // 保留原作者写的行内注释
            xcOrders.setStatus("600002");//订单状态为交易成功 // 执行语句
            ordersMapper.updateById(xcOrders); // 执行语句

            //将消息写到数据库 // 保留原作者写的行内注释
            MqMessage mqMessage = mqMessageService.addMessage("payresult_notify", xcOrders.getOutBusinessId(), xcOrders.getOrderType(), null); // 把 mqMessageService.addMessage("payresult_notify", xcOrders.getOutBusinessId(), xcOrders.getOrderType(), null) 赋值给 mqMessage
            //发送消息 // 保留原作者写的行内注释
            notifyPayResult(mqMessage); // 执行语句

        } // 代码块结束




    } // 代码块结束



    @Override // 使用注解 @Override
    public void notifyPayResult(MqMessage message) { // 定义方法 notifyPayResult(...)

        //消息内容 // 保留原作者写的行内注释
        String jsonString = JSON.toJSONString(message); // 把 JSON.toJSONString(message) 赋值给 jsonString
        //创建一个持久化消息 // 保留原作者写的行内注释
        Message messageObj = MessageBuilder.withBody(jsonString.getBytes(StandardCharsets.UTF_8)).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build(); // 把 MessageBuilder.withBody(jsonString.getBytes(StandardCharsets.UTF_8)).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build() 的返回值赋给 messageObj

        //消息id // 保留原作者写的行内注释
        Long id = message.getId(); // 把 message.getId() 的返回值赋给 id

        //全局消息id // 保留原作者写的行内注释
        CorrelationData correlationData = new CorrelationData(id.toString()); // 创建 CorrelationData 对象并赋值给 correlationData

        //使用correlationData指定回调方法 // 保留原作者写的行内注释
        correlationData.getFuture().addCallback(result->{ // 定义方法 方法(...)
            if(result.isAck()){ // 定义方法 方法(...)
                //消息成功发送到了交换机 // 保留原作者写的行内注释
                log.debug("发送消息成功:{}",jsonString); // 执行语句
                //将消息从数据库表mq_message删除 // 保留原作者写的行内注释
                mqMessageService.completed(id); // 执行语句

            }else{ // 代码逻辑
                //消息发送失败 // 保留原作者写的行内注释
                log.debug("发送消息失败:{}",jsonString); // 执行语句
            } // 代码块结束

        },ex->{ // 代码逻辑
            //发生异常了 // 保留原作者写的行内注释
            log.debug("发送消息异常:{}",jsonString); // 执行语句
        }); // 执行语句
        //发送消息 // 保留原作者写的行内注释
        rabbitTemplate.convertAndSend(PayNotifyConfig.PAYNOTIFY_EXCHANGE_FANOUT,"",messageObj,correlationData); // 执行语句
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 保存支付记录 // 保留原作者写的块注释
     * @param orders // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public XcPayRecord createPayRecord(XcOrders orders){ // 定义方法 createPayRecord(...)
        //订单id // 保留原作者写的行内注释
        Long orderId = orders.getId(); // 把 orders.getId() 的返回值赋给 orderId
        XcOrders xcOrders = ordersMapper.selectById(orderId); // 把 ordersMapper.selectById(orderId) 赋值给 xcOrders
        //如果此订单不存在不能添加支付记录 // 保留原作者写的行内注释
        if(xcOrders == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("订单不存在"); // 执行语句
        } // 代码块结束
        //订单状态 // 保留原作者写的行内注释
        String status = xcOrders.getStatus(); // 把 xcOrders.getStatus() 的返回值赋给 status
        //如果此订单支付结果为成功,不再添加支付记录,避免重复支付 // 保留原作者写的行内注释
        if("601002".equals(status)){//支付成功 // 定义方法 方法(...)
            XueChengPlusException.cast("此订单已支付"); // 执行语句
        } // 代码块结束
        //添加支付记录 // 保留原作者写的行内注释
        XcPayRecord xcPayRecord = new XcPayRecord(); // 创建 XcPayRecord 对象并赋值给 xcPayRecord
        xcPayRecord.setPayNo(IdWorkerUtils.getInstance().nextId());//支付记录号,将来要传给支付宝 // 执行语句
        xcPayRecord.setOrderId(orderId); // 执行语句
        xcPayRecord.setOrderName(xcOrders.getOrderName()); // 执行语句
        xcPayRecord.setTotalPrice(xcOrders.getTotalPrice()); // 执行语句
        xcPayRecord.setCurrency("CNY"); // 执行语句
        xcPayRecord.setCreateDate(LocalDateTime.now()); // 执行语句
        xcPayRecord.setStatus("601001");//未支付 // 执行语句
        xcPayRecord.setUserId(xcOrders.getUserId()); // 执行语句
        int insert = payRecordMapper.insert(xcPayRecord); // 把 payRecordMapper.insert(xcPayRecord) 赋值给 insert
        if(insert<=0){ // 定义方法 方法(...)
            XueChengPlusException.cast("插入支付记录失败"); // 执行语句
        } // 代码块结束
        return xcPayRecord; // 返回 xcPayRecord
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 保存订单信息 // 保留原作者写的块注释
     * @param userId // 保留原作者写的块注释
     * @param addOrderDto // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public XcOrders saveXcOrders(String userId, AddOrderDto addOrderDto){ // 定义方法 saveXcOrders(...)
        //插入订单表,订单主表,订单明细表 // 保留原作者写的行内注释
        //进行幂等性判断,同一个选课记录只能有一个订单 // 保留原作者写的行内注释
        XcOrders xcOrders = getOrderByBusinessId(addOrderDto.getOutBusinessId()); // 把 getOrderByBusinessId(addOrderDto.getOutBusinessId()) 赋值给 xcOrders
        if(xcOrders!=null){ // 定义方法 方法(...)
            return xcOrders; // 返回 xcOrders
        } // 代码块结束

        //插入订单主表 // 保留原作者写的行内注释
        xcOrders = new XcOrders(); // 创建 XcOrders 对象并赋值给 xcOrders
        //使用雪花算法生成订单号 // 保留原作者写的行内注释
        xcOrders.setId(IdWorkerUtils.getInstance().nextId()); // 执行语句
        xcOrders.setTotalPrice(addOrderDto.getTotalPrice()); // 执行语句
        xcOrders.setCreateDate(LocalDateTime.now()); // 执行语句
        xcOrders.setStatus("600001");//未支付 // 执行语句
        xcOrders.setUserId(userId); // 执行语句
        xcOrders.setOrderType("60201");//订单类型 // 执行语句
        xcOrders.setOrderName(addOrderDto.getOrderName()); // 执行语句
        xcOrders.setOrderDescrip(addOrderDto.getOrderDescrip()); // 执行语句
        xcOrders.setOrderDetail(addOrderDto.getOrderDetail()); // 执行语句
        xcOrders.setOutBusinessId(addOrderDto.getOutBusinessId());//如果是选课这里记录选课表的id // 执行语句
        int insert = ordersMapper.insert(xcOrders); // 把 ordersMapper.insert(xcOrders) 赋值给 insert
        if(insert<=0){ // 定义方法 方法(...)
            XueChengPlusException.cast("添加订单失败"); // 执行语句
        } // 代码块结束
        //订单id // 保留原作者写的行内注释
        Long orderId = xcOrders.getId(); // 把 xcOrders.getId() 的返回值赋给 orderId
        //插入订单明细表 // 保留原作者写的行内注释
        //将前端传入的明细json串转成List // 保留原作者写的行内注释
        String orderDetailJson = addOrderDto.getOrderDetail(); // 把 addOrderDto.getOrderDetail() 的返回值赋给 orderDetailJson
        List<XcOrdersGoods> xcOrdersGoods = JSON.parseArray(orderDetailJson, XcOrdersGoods.class); // 把 JSON.parseArray(orderDetailJson, XcOrdersGoods.class) 赋值给 xcOrdersGoods
        //遍历xcOrdersGoods插入订单明细表 // 保留原作者写的行内注释
        xcOrdersGoods.forEach(goods->{ // 定义方法 方法(...)

            goods.setOrderId(orderId); // 执行语句
            //插入订单明细表 // 保留原作者写的行内注释
            int insert1 = ordersGoodsMapper.insert(goods); // 把 ordersGoodsMapper.insert(goods) 赋值给 insert1

        }); // 执行语句
        return xcOrders; // 返回 xcOrders

    } // 代码块结束


    /** // 保留原作者写的块注释
     * 根据业务id查询订单 ,业务id是选课记录表中的主键 // 保留原作者写的块注释
     * @param businessId // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public XcOrders getOrderByBusinessId(String businessId) { // 定义方法 getOrderByBusinessId(...)
        XcOrders orders = ordersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId)); // 把 ordersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId)) 赋值给 orders
        return orders; // 返回 orders
    } // 代码块结束



} // 代码块结束

文件:xuecheng-plus-orders/service/main/com/xuecheng/orders/service/OrderService.java

package com.xuecheng.orders.service; // 声明类所在的包路径

import com.xuecheng.messagesdk.model.po.MqMessage; // 导入 MqMessage 类
import com.xuecheng.orders.model.dto.AddOrderDto; // 导入 AddOrderDto 类
import com.xuecheng.orders.model.dto.PayRecordDto; // 导入 PayRecordDto 类
import com.xuecheng.orders.model.dto.PayStatusDto; // 导入 PayStatusDto 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 订单相关的service接口 // 保留原作者写的块注释
 * @date 2023/2/26 10:11 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface OrderService { // 定义 interface OrderService

 /** // 保留原作者写的块注释
  * @description 创建商品订单 // 保留原作者写的块注释
  * @param addOrderDto 订单信息 // 保留原作者写的块注释
  * @return PayRecordDto 支付记录(包括二维码) // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/10/4 11:02 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto); // 执行语句

 /** // 保留原作者写的块注释
  * @description 查询支付记录 // 保留原作者写的块注释
  * @param payNo  交易记录号 // 保留原作者写的块注释
  * @return com.xuecheng.orders.model.po.XcPayRecord // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/10/20 23:38 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public XcPayRecord getPayRecordByPayno(String payNo); // 执行语句

 /** // 保留原作者写的块注释
  * 请求支付宝查询支付结果 // 保留原作者写的块注释
  * @param payNo 支付记录id // 保留原作者写的块注释
  * @return 支付记录信息 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public PayRecordDto queryPayResult(String payNo); // 执行语句

 /** // 保留原作者写的块注释
  * 保存支付状态 // 保留原作者写的块注释
  * @param payStatusDto // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public void saveAliPayStatus(PayStatusDto payStatusDto); // 执行语句

 /** // 保留原作者写的块注释
  * 发送通知结果 // 保留原作者写的块注释
  * @param message // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public void notifyPayResult(MqMessage message); // 执行语句
} // 代码块结束

文件:xuecheng-plus-orders/service_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-orders</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>xuecheng-plus-orders-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-message-sdk</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-orders-model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- mybatis plus的依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!-- Spring Boot 集成 Junit -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Spring Boot 集成 log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- Spring Cloud 微服务远程调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- 支付宝SDK -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>3.7.73.ALL</version>
        </dependency>

        <!-- 支付宝SDK依赖的日志 -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
    </dependencies>

</project>

文件:xuecheng-plus-orders/test_service/com/xuecheng/orders/AliPayTest.java

package com.xuecheng.orders; // 声明类所在的包路径

import com.alibaba.fastjson.JSONObject; // 导入 JSONObject 类
import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.request.AlipayTradeQueryRequest; // 导入 AlipayTradeQueryRequest 类
import com.alipay.api.response.AlipayTradeQueryResponse; // 导入 AlipayTradeQueryResponse 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.boot.test.context.SpringBootTest; // 导入 SpringBootTest 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 请求支付宝查询订单状态 // 保留原作者写的块注释
 * @date 2023/2/25 16:49 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@SpringBootTest // 使用注解 @SpringBootTest
public class AliPayTest { // 定义 class AliPayTest

    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    @Test // 使用注解 @Test
    public void queryPayResult() throws AlipayApiException { // 定义方法 queryPayResult(...)

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); // 创建 AlipayTradeQueryRequest 对象并赋值给 request
        JSONObject bizContent = new JSONObject(); // 创建 JSONObject 对象并赋值给 bizContent
        bizContent.put("out_trade_no", "1629685380690747392"); // 执行语句
        //bizContent.put("trade_no", "2014112611001004680073956707"); // 保留原作者写的行内注释
        request.setBizContent(bizContent.toString()); // 执行语句
        AlipayTradeQueryResponse response = alipayClient.execute ( request ); //通过alipayClient调用API,获得对应的response类 // 把 alipayClient.execute ( request ) 赋值给 response
        String body = response.getBody(); // 把 response.getBody() 的返回值赋给 body
        System.out.print( body); // 执行语句

} // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/test_service/com/xuecheng/orders/OrdersApplication.java

package com.xuecheng.orders; // 声明类所在的包路径


import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类
import org.springframework.cloud.openfeign.EnableFeignClients; // 导入 EnableFeignClients 类

@SpringBootApplication // 使用注解 @SpringBootApplication
public class OrdersApplication { // 定义 class OrdersApplication
	public static void main(String[] args) { // 定义方法 main(...)
		SpringApplication.run(OrdersApplication.class, args); // 执行语句
	} // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/test_service/com/xuecheng/orders/Test1.java

package com.xuecheng.orders; // 声明类所在的包路径

import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.boot.test.context.SpringBootTest; // 导入 SpringBootTest 类

/** // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/10/2 10:32 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 @SpringBootTest // 使用注解 @SpringBootTest
public class Test1 { // 定义 class Test1


  @Test // 使用注解 @Test
 public void test(){ // 定义方法 test(...)

  } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-orders/test_service/resources/bootstrap.yml

spring:
  application:
    name: orders-service
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true

  #profiles默认为dev
  profiles:
    active: dev




文件:xuecheng-plus-orders/test_service/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="180" packages="">
    <properties>
        <property name="logdir">logs</property>
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${PATTERN}"/>
        </Console>

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log"
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true">
            <PatternLayout pattern="${PATTERN}"/>
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log"
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true">
            <PatternLayout pattern="${PATTERN}"/>
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true">
            <AppenderRef ref="ErrorAppender"/>
            <AppenderRef ref="DebugAppender"/>
        </Async>
    </Appenders>
    
    <Loggers>
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO">
        </logger>
        <logger name="org.mybatis" level="INFO">
        </logger>
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG">
        </logger>

        <logger name="springfox" level="INFO">
        </logger>
		<logger name="org.apache.http" level="INFO">
        </logger>
        <logger name="com.netflix.discovery" level="INFO">
        </logger>
        
        <logger name="RocketmqCommon"  level="INFO" >
		</logger>
		
		<logger name="RocketmqRemoting" level="INFO"  >
		</logger>
		
		<logger name="RocketmqClient" level="WARN">
		</logger>

        <logger name="org.dromara.hmily" level="WARN">
        </logger>

        <logger name="org.dromara.hmily.lottery" level="WARN">
        </logger>

        <logger name="org.dromara.hmily.bonuspoint" level="WARN">
        </logger>
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true">
            <AppenderRef ref="AsyncAppender"/>
            <AppenderRef ref="Console"/>
            <AppenderRef ref="DebugAppender"/>
        </Root>
    </Loggers>
</Configuration>

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-orders</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-orders-api</artifactId> <!-- SQL 语句片段 -->

    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-orders-model</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-orders-service</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!--cloud的基础环境包-->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-context</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 的 Spring Web MVC 集成 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-web</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 集成 Junit -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-test</artifactId> <!-- SQL 语句片段 -->
            <scope>test</scope> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-validation</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
            <exclusions> <!-- SQL 语句片段 -->
                <exclusion> <!-- SQL 语句片段 -->
                    <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                    <artifactId>spring-boot-starter-logging</artifactId> <!-- SQL 语句片段 -->
                </exclusion> <!-- SQL 语句片段 -->
            </exclusions> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 log4j2 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-log4j2</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 swagger -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.spring4all</groupId> <!-- SQL 语句片段 -->
            <artifactId>swagger-spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->


        <!--认证相关-->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-security</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-oauth2</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.apache.commons</groupId> <!-- SQL 语句片段 -->
            <artifactId>commons-lang3</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.google.zxing</groupId> <!-- SQL 语句片段 -->
            <artifactId>core</artifactId> <!-- SQL 语句片段 -->
            <version>3.3.3</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.google.zxing</groupId> <!-- SQL 语句片段 -->
            <artifactId>javase</artifactId> <!-- SQL 语句片段 -->
            <version>3.3.3</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
    </dependencies> <!-- SQL 语句片段 -->

</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/orders/api/OrderController.java

package com.xuecheng.orders.api; // 声明类所在的包路径

import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.internal.util.AlipaySignature; // 导入 AlipaySignature 类
import com.alipay.api.request.AlipayTradeWapPayRequest; // 导入 AlipayTradeWapPayRequest 类
import com.xuecheng.base.exception.XueChengPlusException; // 导入 XueChengPlusException 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import com.xuecheng.orders.model.dto.AddOrderDto; // 导入 AddOrderDto 类
import com.xuecheng.orders.model.dto.PayRecordDto; // 导入 PayRecordDto 类
import com.xuecheng.orders.model.dto.PayStatusDto; // 导入 PayStatusDto 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类
import com.xuecheng.orders.service.OrderService; // 导入 OrderService 类
import com.xuecheng.orders.util.SecurityUtil; // 导入 SecurityUtil 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Controller; // 导入 Controller 类
import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 类
import org.springframework.web.bind.annotation.PostMapping; // 导入 PostMapping 类
import org.springframework.web.bind.annotation.RequestBody; // 导入 RequestBody 类
import org.springframework.web.bind.annotation.ResponseBody; // 导入 ResponseBody 类

import javax.servlet.http.HttpServletRequest; // 导入 HttpServletRequest 类
import javax.servlet.http.HttpServletResponse; // 导入 HttpServletResponse 类
import java.io.IOException; // 导入 IOException 类
import java.io.UnsupportedEncodingException; // 导入 UnsupportedEncodingException 类
import java.util.HashMap; // 导入 HashMap 类
import java.util.Iterator; // 导入 Iterator 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 订单相关的接口 // 保留原作者写的块注释
 * @date 2023/2/26 10:09 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Api(value = "订单支付接口", tags = "订单支付接口") // 使用注解 @Api(value = "订单支付接口", tags = "订单支付接口")
@Slf4j // 使用注解 @Slf4j
@Controller // 使用注解 @Controller
public class OrderController { // 定义 class OrderController

    @Autowired // 使用注解 @Autowired
    OrderService orderService; // 执行语句

    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    @ApiOperation("生成支付二维码") // 使用注解 @ApiOperation("生成支付二维码")
    @PostMapping("/generatepaycode") // 使用注解 @PostMapping("/generatepaycode")
    @ResponseBody // 使用注解 @ResponseBody
    public PayRecordDto generatePayCode(@RequestBody AddOrderDto addOrderDto) { // 定义方法 generatePayCode(...)

        SecurityUtil.XcUser user = SecurityUtil.getUser(); // 把 SecurityUtil.getUser() 的返回值赋给 user
        String userId = user.getId(); // 把 user.getId() 的返回值赋给 userId

        //调用service,完成插入订单信息、插入支付记录、生成支付二维码 // 保留原作者写的行内注释
        PayRecordDto payRecordDto = orderService.createOrder(userId, addOrderDto); // 把 orderService.createOrder(userId, addOrderDto) 赋值给 payRecordDto

        return payRecordDto; // 返回 payRecordDto
    } // 代码块结束

    @ApiOperation("扫码下单接口") // 使用注解 @ApiOperation("扫码下单接口")
    @GetMapping("/requestpay") // 使用注解 @GetMapping("/requestpay")
    public void requestpay(String payNo, HttpServletResponse httpResponse) throws IOException, AlipayApiException { // 定义方法 requestpay(...)

        //传入了支付记录号,判断支付记录号是否存在 // 保留原作者写的行内注释
        XcPayRecord payRecordByPayno = orderService.getPayRecordByPayno(payNo); // 把 orderService.getPayRecordByPayno(payNo) 赋值给 payRecordByPayno
        if(payRecordByPayno == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("支付记录不存在"); // 执行语句
        } // 代码块结束
        //支付结果 // 保留原作者写的行内注释
        String status = payRecordByPayno.getStatus(); // 把 payRecordByPayno.getStatus() 的返回值赋给 status
        if ("601002".equals(status)) { // 定义方法 方法(...)

            XueChengPlusException.cast("已支付,无需重复支付"); // 执行语句
        } // 代码块结束

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request // 创建 AlipayTradeWapPayRequest 对象并赋值给 alipayRequest
//        alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp"); // 保留原作者写的行内注释
        alipayRequest.setNotifyUrl("http://tjxt-user-t.itheima.net/xuecheng/orders/paynotify");//在公共参数中设置回跳和通知地址 // 代码逻辑
        alipayRequest.setBizContent("{" + // 代码逻辑
                "    \"out_trade_no\":\""+payNo+"\"," + // 代码逻辑
                "    \"total_amount\":"+payRecordByPayno.getTotalPrice()+"," + // 代码逻辑
                "    \"subject\":\""+payRecordByPayno.getOrderName()+"\"," + // 代码逻辑
                "    \"product_code\":\"QUICK_WAP_WAY\"" + // 代码逻辑
                "  }");//填充业务参数 // 执行语句
        String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK请求支付宝下单 // 把 alipayClient.pageExecute(alipayRequest).getBody() 的返回值赋给 form
        httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET); // 把 " + AlipayConfig.CHARSET) 赋值给 httpResponse.setContentType("text/html;charset
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面 // 执行语句
        httpResponse.getWriter().flush(); // 执行语句


    } // 代码块结束

    @ApiOperation("查询支付结果") // 使用注解 @ApiOperation("查询支付结果")
    @GetMapping("/payresult") // 使用注解 @GetMapping("/payresult")
    @ResponseBody // 使用注解 @ResponseBody
    public PayRecordDto payresult(String payNo) throws IOException { // 定义方法 payresult(...)
        //查询支付结果 // 保留原作者写的行内注释
        PayRecordDto payRecordDto = orderService.queryPayResult(payNo); // 把 orderService.queryPayResult(payNo) 赋值给 payRecordDto
        return payRecordDto; // 返回 payRecordDto

    } // 代码块结束

    //接收支付宝通知 // 保留原作者写的行内注释
    @PostMapping("/paynotify") // 使用注解 @PostMapping("/paynotify")
    public void paynotify(HttpServletRequest request, HttpServletResponse response) throws IOException, AlipayApiException { // 定义方法 paynotify(...)

        //获取支付宝POST过来反馈信息 // 保留原作者写的行内注释
        Map<String,String> params = new HashMap<String,String>(); // 创建 HashMap<String,String> 对象并赋值给 params
        Map requestParams = request.getParameterMap(); // 把 request.getParameterMap() 的返回值赋给 requestParams
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { // 定义方法 方法(...)
            String name = (String) iter.next(); // 把 (String) iter.next() 的返回值赋给 name
            String[] values = (String[]) requestParams.get(name); // 把 (String[]) requestParams.get(name) 赋值给 values
            String valueStr = ""; // 把 "" 赋值给 valueStr
            for (int i = 0; i < values.length; i++) { // 定义方法 方法(...)
                valueStr = (i == values.length - 1) ? valueStr + values[i] // 代码逻辑
                        : valueStr + values[i] + ","; // 执行语句
            } // 代码块结束
            params.put(name, valueStr); // 执行语句
        } // 代码块结束
        boolean verify_result = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2"); // 把 AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2") 赋值给 verify_result

        if(verify_result){//验证成功 // 定义方法 方法(...)
            //商户订单号 // 保留原作者写的行内注释
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 out_trade_no
            //支付宝交易号 // 保留原作者写的行内注释
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_no
            //交易金额 // 保留原作者写的行内注释
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 total_amount
            //交易状态 // 保留原作者写的行内注释
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_status
            if (trade_status.equals("TRADE_SUCCESS")){ // 定义方法 方法(...)
                //更新支付记录表的支付状态为成功,订单表的状态为成功 // 保留原作者写的行内注释
                PayStatusDto payStatusDto = new PayStatusDto(); // 创建 PayStatusDto 对象并赋值给 payStatusDto
                payStatusDto.setTrade_status(trade_status); // 执行语句
                payStatusDto.setTrade_no(trade_no); // 执行语句
                payStatusDto.setOut_trade_no(out_trade_no); // 执行语句
                payStatusDto.setTotal_amount(total_amount); // 执行语句
                payStatusDto.setApp_id(APP_ID); // 执行语句
                orderService.saveAliPayStatus(payStatusDto); // 执行语句
            } // 代码块结束

            response.getWriter().write("success"); // 执行语句

        }else{//验证失败 // 代码逻辑
            response.getWriter().write("fail"); // 执行语句
        } // 代码块结束
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/orders/api/PayTestController.java

package com.xuecheng.orders.api; // 声明类所在的包路径

import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.internal.util.AlipaySignature; // 导入 AlipaySignature 类
import com.alipay.api.request.AlipayTradeWapPayRequest; // 导入 AlipayTradeWapPayRequest 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Controller; // 导入 Controller 类
import org.springframework.web.bind.annotation.PostMapping; // 导入 PostMapping 类
import org.springframework.web.bind.annotation.RequestMapping; // 导入 RequestMapping 类

import javax.servlet.ServletException; // 导入 ServletException 类
import javax.servlet.http.HttpServletRequest; // 导入 HttpServletRequest 类
import javax.servlet.http.HttpServletResponse; // 导入 HttpServletResponse 类
import java.io.IOException; // 导入 IOException 类
import java.io.UnsupportedEncodingException; // 导入 UnsupportedEncodingException 类
import java.util.HashMap; // 导入 HashMap 类
import java.util.Iterator; // 导入 Iterator 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 扫码支付的测试 // 保留原作者写的块注释
 * @date 2023/2/25 16:17 // 保留原作者写的块注释
 */ // 保留原作者写的块注释

@Controller // 使用注解 @Controller
public class PayTestController { // 定义 class PayTestController
    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    //下单接口测试 // 保留原作者写的行内注释
    @RequestMapping("/alipaytest") // 使用注解 @RequestMapping("/alipaytest")
    public void doPost(HttpServletRequest httpRequest, // 代码逻辑
                       HttpServletResponse httpResponse) throws ServletException, IOException, AlipayApiException { // 代码逻辑

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request // 创建 AlipayTradeWapPayRequest 对象并赋值给 alipayRequest
//        alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp"); // 保留原作者写的行内注释
        alipayRequest.setNotifyUrl("http://tjxt-user-t.itheima.net/xuecheng/orders/paynotify");//在公共参数中设置回跳和通知地址 // 代码逻辑
        alipayRequest.setBizContent("{" + // 代码逻辑
                "    \"out_trade_no\":\"202303200101020011\"," + // 代码逻辑
                "    \"total_amount\":0.1," + // 代码逻辑
                "    \"subject\":\"Iphone14 16G\"," + // 代码逻辑
                "    \"product_code\":\"QUICK_WAP_WAY\"" + // 代码逻辑
                "  }");//填充业务参数 // 执行语句
        String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单 // 把 alipayClient.pageExecute(alipayRequest).getBody() 的返回值赋给 form
        httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET); // 把 " + AlipayConfig.CHARSET) 赋值给 httpResponse.setContentType("text/html;charset
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面 // 执行语句
        httpResponse.getWriter().flush(); // 执行语句
    } // 代码块结束

    //支付结果通知 // 保留原作者写的行内注释
    @PostMapping("/paynotifytest") // 使用注解 @PostMapping("/paynotifytest")
    public void paynotify(HttpServletRequest request,HttpServletResponse response) throws IOException, AlipayApiException { // 定义方法 paynotify(...)

        //获取支付宝POST过来反馈信息 // 保留原作者写的行内注释
        Map<String,String> params = new HashMap<String,String>(); // 创建 HashMap<String,String> 对象并赋值给 params
        Map requestParams = request.getParameterMap(); // 把 request.getParameterMap() 的返回值赋给 requestParams
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { // 定义方法 方法(...)
            String name = (String) iter.next(); // 把 (String) iter.next() 的返回值赋给 name
            String[] values = (String[]) requestParams.get(name); // 把 (String[]) requestParams.get(name) 赋值给 values
            String valueStr = ""; // 把 "" 赋值给 valueStr
            for (int i = 0; i < values.length; i++) { // 定义方法 方法(...)
                valueStr = (i == values.length - 1) ? valueStr + values[i] // 代码逻辑
                        : valueStr + values[i] + ","; // 执行语句
            } // 代码块结束
            //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 // 保留原作者写的行内注释
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); // 保留原作者写的行内注释
            params.put(name, valueStr); // 执行语句
        } // 代码块结束
        //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// // 保留原作者写的行内注释

        //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// // 保留原作者写的行内注释
        //计算得出通知验证结果 // 保留原作者写的行内注释
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type) // 保留原作者写的行内注释
        boolean verify_result = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2"); // 把 AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2") 赋值给 verify_result

        if(verify_result){//验证成功 // 定义方法 方法(...)
            ////////////////////////////////////////////////////////////////////////////////////////// // 保留原作者写的行内注释
            //请在这里加上商户的业务逻辑程序代码 // 保留原作者写的行内注释
            //商户订单号 // 保留原作者写的行内注释

            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 out_trade_no
            //支付宝交易号 // 保留原作者写的行内注释

            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_no

            //交易状态 // 保留原作者写的行内注释
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8"); // 创建 String 对象并赋值给 trade_status


            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— // 保留原作者写的行内注释

            if(trade_status.equals("TRADE_FINISHED")){ // 定义方法 方法(...)
                //判断该笔订单是否在商户网站中已经做过处理 // 保留原作者写的行内注释
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 保留原作者写的行内注释
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 保留原作者写的行内注释
                //如果有做过处理,不执行商户的业务程序 // 保留原作者写的行内注释

                //注意: // 保留原作者写的行内注释
                //如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 // 保留原作者写的行内注释
                //如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。 // 保留原作者写的行内注释
            } else if (trade_status.equals("TRADE_SUCCESS")){ // 定义方法 if(...)
                //判断该笔订单是否在商户网站中已经做过处理 // 保留原作者写的行内注释
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 保留原作者写的行内注释
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 保留原作者写的行内注释
                //如果有做过处理,不执行商户的业务程序 // 保留原作者写的行内注释
                System.out.println(trade_status); // 执行语句
                //注意: // 保留原作者写的行内注释
                //如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。 // 保留原作者写的行内注释
            } // 代码块结束

            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— // 保留原作者写的行内注释
            response.getWriter().write("success"); // 执行语句

            ////////////////////////////////////////////////////////////////////////////////////////// // 保留原作者写的行内注释
        }else{//验证失败 // 代码逻辑
            response.getWriter().write("fail"); // 执行语句
        } // 代码块结束


    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/orders/config/ResouceServerConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; // 导入 EnableGlobalMethodSecurity 类
import org.springframework.security.config.annotation.web.builders.HttpSecurity; // 导入 HttpSecurity 类
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; // 导入 EnableResourceServer 类
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; // 导入 ResourceServerConfigurerAdapter 类
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; // 导入 ResourceServerSecurityConfigurer 类
import org.springframework.security.oauth2.provider.token.TokenStore; // 导入 TokenStore 类

/** // 保留原作者写的块注释
 * @author Administrator // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 **/ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
@EnableResourceServer // 使用注解 @EnableResourceServer
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) // 使用注解 @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class ResouceServerConfig extends ResourceServerConfigurerAdapter { // 定义 class ResouceServerConfig


    //资源服务标识 // 保留原作者写的行内注释
    public static final String RESOURCE_ID = "xuecheng-plus"; // 把 "xuecheng-plus" 赋值给 RESOURCE_ID

    @Autowired // 使用注解 @Autowired
    TokenStore tokenStore; // 执行语句

    @Override // 使用注解 @Override
    public void configure(ResourceServerSecurityConfigurer resources) { // 定义方法 configure(...)
        resources.resourceId(RESOURCE_ID)//资源 id // 代码逻辑
                .tokenStore(tokenStore) // 代码逻辑
                .stateless(true); // 执行语句
    } // 代码块结束

    @Override // 使用注解 @Override
    public void configure(HttpSecurity http) throws Exception { // 定义方法 configure(...)
        http.csrf().disable() // 代码逻辑
                .authorizeRequests() // 代码逻辑
//                .antMatchers("/r/**","/course/**").authenticated()//所有/r/**的请求必须认证通过 // 保留原作者写的行内注释
                .anyRequest().permitAll() // 代码逻辑
        ; // 执行语句
    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/orders/config/TokenConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类
import org.springframework.security.oauth2.provider.token.TokenStore; // 导入 TokenStore 类
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; // 导入 JwtAccessTokenConverter 类
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; // 导入 JwtTokenStore 类

/** // 保留原作者写的块注释
 * @author Administrator // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 **/ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class TokenConfig { // 定义 class TokenConfig

    //jwt签名密钥,与认证服务保持一致 // 保留原作者写的行内注释
    private String SIGNING_KEY = "mq123"; // 把 "mq123" 赋值给 SIGNING_KEY

    @Bean // 使用注解 @Bean
    public TokenStore tokenStore() { // 定义方法 tokenStore(...)
        //JWT令牌存储方案 // 保留原作者写的行内注释
        return new JwtTokenStore(accessTokenConverter()); // 返回 new JwtTokenStore(accessTokenConverter())
    } // 代码块结束

    @Bean // 使用注解 @Bean
    public JwtAccessTokenConverter accessTokenConverter() { // 定义方法 accessTokenConverter(...)
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); // 创建 JwtAccessTokenConverter 对象并赋值给 converter
        converter.setSigningKey(SIGNING_KEY); // 执行语句
        return converter; // 返回 converter
    } // 代码块结束

   /* @Bean // 保留原作者写的块注释
    public TokenStore tokenStore() { // 定义方法 tokenStore(...)
        //使用内存存储令牌(普通令牌) // 保留原作者写的行内注释
        return new InMemoryTokenStore(); // 返回 new InMemoryTokenStore()
    }*/ // 代码逻辑
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/orders/util/SecurityUtil.java

package com.xuecheng.orders.util; // 声明类所在的包路径

import com.alibaba.fastjson.JSON; // 导入 JSON 类
import lombok.Data; // 导入 Data 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.security.core.context.SecurityContextHolder; // 导入 SecurityContextHolder 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/*** // 保留原作者写的块注释
 * 获取当前登录用户信息,使用解析jwt中的用户信息 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
public class SecurityUtil { // 定义 class SecurityUtil

    public static XcUser getUser() { // 定义方法 getUser(...)
        try { // 尝试执行可能抛出异常的代码
            Object principalObj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // 把 SecurityContextHolder.getContext().getAuthentication().getPrincipal() 的返回值赋给 principalObj
            if (principalObj instanceof String) { // 定义方法 方法(...)
                //取出用户身份信息 // 保留原作者写的行内注释
                String principal = principalObj.toString(); // 把 principalObj.toString() 的返回值赋给 principal
                //将json转成对象 // 保留原作者写的行内注释
                XcUser user = JSON.parseObject(principal, XcUser.class); // 把 JSON.parseObject(principal, XcUser.class) 赋值给 user
                return user; // 返回 user
            } // 代码块结束
        } catch (Exception e) { // 定义方法 catch(...)
            log.error("获取当前登录用户身份出错:{}", e.getMessage()); // 执行语句
            e.printStackTrace(); // 执行语句
        } // 代码块结束

        return null; // 返回 null
    } // 代码块结束

    @Data // 使用注解 @Data
    public static class XcUser implements Serializable { // 代码逻辑

        private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

        private String id; // 执行语句

        private String username; // 执行语句

        private String password; // 执行语句

        private String salt; // 执行语句

        private String name; // 执行语句
        private String nickname; // 执行语句
        private String wxUnionid; // 执行语句
        private String companyId; // 执行语句
        /** // 保留原作者写的块注释
         * 头像 // 保留原作者写的块注释
         */ // 保留原作者写的块注释
        private String userpic; // 执行语句

        private String utype; // 执行语句

        private LocalDateTime birthday; // 执行语句

        private String sex; // 执行语句

        private String email; // 执行语句

        private String cellphone; // 执行语句

        private String qq; // 执行语句

        /** // 保留原作者写的块注释
         * 用户状态 // 保留原作者写的块注释
         */ // 保留原作者写的块注释
        private String status; // 执行语句

        private LocalDateTime createTime; // 执行语句

        private LocalDateTime updateTime; // 执行语句


    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/java/com/xuecheng/OrdersApiApplication.java

package com.xuecheng; // 声明类所在的包路径

import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类

@SpringBootApplication // 使用注解 @SpringBootApplication
public class OrdersApiApplication { // 定义 class OrdersApiApplication

    public static void main(String[] args) { // 定义方法 main(...)
        SpringApplication.run(OrdersApiApplication.class, args); // 执行语句
    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/resources/bootstrap.yml

#微服务配置
spring:
  application:
    name: orders-api
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        extension-configs:
          - data-id: orders-service-${spring.profiles.active}.yaml
            group: xuecheng-plus-project
            refresh: true
        shared-configs:
          - data-id: swagger-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: rabbitmq-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true

  profiles:
    active: dev

文件:xuecheng-plus-orders/xuecheng-plus-orders-api/src/main/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<Configuration monitorInterval="180" packages=""> <!-- SQL 语句片段 -->
    <properties> <!-- SQL 语句片段 -->
        <property name="logdir">logs</property> <!-- SQL 语句片段 -->
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property> <!-- SQL 语句片段 -->
    </properties> <!-- SQL 语句片段 -->
    <Appenders> <!-- SQL 语句片段 -->
        <Console name="Console" target="SYSTEM_OUT"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
        </Console> <!-- SQL 语句片段 -->

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="ErrorAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Async> <!-- SQL 语句片段 -->
    </Appenders> <!-- SQL 语句片段 -->
    
    <Loggers> <!-- SQL 语句片段 -->
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="org.mybatis" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="springfox" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		<logger name="org.apache.http" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="com.netflix.discovery" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        
        <logger name="RocketmqCommon"  level="INFO" > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqRemoting" level="INFO"  > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqClient" level="WARN"> <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.lottery" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.bonuspoint" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="AsyncAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="Console"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Root> <!-- SQL 语句片段 -->
    </Loggers> <!-- SQL 语句片段 -->
</Configuration> <!-- SQL 语句片段 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-orders</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-orders-model</artifactId> <!-- SQL 语句片段 -->


    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-base</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!--存在mybatisplus注解添加相关注解保证不报错-->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.baomidou</groupId> <!-- SQL 语句片段 -->
            <artifactId>mybatis-plus-annotation</artifactId> <!-- SQL 语句片段 -->
            <version>${mybatis-plus-boot-starter.version}</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.baomidou</groupId> <!-- SQL 语句片段 -->
            <artifactId>mybatis-plus-core</artifactId> <!-- SQL 语句片段 -->
            <version>${mybatis-plus-boot-starter.version}</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.projectlombok</groupId> <!-- SQL 语句片段 -->
            <artifactId>lombok</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
    </dependencies> <!-- SQL 语句片段 -->

</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model/dto/AddOrderDto.java

package com.xuecheng.orders.model.dto; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 创建商品订单 // 保留原作者写的块注释
 * @date 2022/10/4 10:21 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class AddOrderDto  { // 定义 class AddOrderDto

    /** // 保留原作者写的块注释
     * 总价 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float totalPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 订单类型 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderType; // 执行语句

    /** // 保留原作者写的块注释
     * 订单名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderName; // 执行语句
    /** // 保留原作者写的块注释
     * 订单描述 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDescrip; // 执行语句

    /** // 保留原作者写的块注释
     * 订单明细json,不可为空 // 保留原作者写的块注释
     * [{"goodsId":"","goodsType":"","goodsName":"","goodsPrice":"","goodsDetail":""},{...}] // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDetail; // 执行语句

    /** // 保留原作者写的块注释
     * 外部系统业务id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outBusinessId; // 执行语句

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model/dto/PayRecordDto.java

package com.xuecheng.orders.model.dto; // 声明类所在的包路径

import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 支付记录dto // 保留原作者写的块注释
 * @date 2022/10/4 11:30 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class PayRecordDto extends XcPayRecord { // 定义 class PayRecordDto

    //二维码 // 保留原作者写的行内注释
    private String qrcode; // 执行语句

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model/dto/PayStatusDto.java

package com.xuecheng.orders.model.dto; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 支付结果数据, 用于接收支付结果通知处理逻辑 // 保留原作者写的块注释
 * @date 2022/10/4 16:49 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class PayStatusDto { // 定义 class PayStatusDto

    //商户订单号 // 保留原作者写的行内注释
    String out_trade_no; // 执行语句
    //支付宝交易号 // 保留原作者写的行内注释
    String trade_no; // 执行语句
    //交易状态 // 保留原作者写的行内注释
    String trade_status; // 执行语句
    //appid // 保留原作者写的行内注释
    String app_id; // 执行语句
    //total_amount // 保留原作者写的行内注释
    String total_amount; // 执行语句
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model/po/XcOrders.java

package com.xuecheng.orders.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.FieldFill; // 导入 FieldFill 类
import com.baomidou.mybatisplus.annotation.TableField; // 导入 TableField 类
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("xc_orders") // 使用注解 @TableName("xc_orders")
public class XcOrders implements Serializable { // 定义 class XcOrders

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 订单号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 总价 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float totalPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 创建时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 交易状态 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 用户id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String userId; // 执行语句


    /** // 保留原作者写的块注释
     * 订单类型 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderType; // 执行语句

    /** // 保留原作者写的块注释
     * 订单名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderName; // 执行语句

    /** // 保留原作者写的块注释
     * 订单描述 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDescrip; // 执行语句

    /** // 保留原作者写的块注释
     * 订单明细json // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderDetail; // 执行语句

    /** // 保留原作者写的块注释
     * 外部系统业务id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outBusinessId; // 执行语句


} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model/po/XcOrdersGoods.java

package com.xuecheng.orders.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.IdType; // 导入 IdType 类
import com.baomidou.mybatisplus.annotation.TableId; // 导入 TableId 类
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("xc_orders_goods") // 使用注解 @TableName("xc_orders_goods")
public class XcOrdersGoods implements Serializable { // 定义 class XcOrdersGoods

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    @TableId(value = "id", type = IdType.AUTO) // 使用注解 @TableId(value = "id", type = IdType.AUTO)
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 订单号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long orderId; // 执行语句

    /** // 保留原作者写的块注释
     * 商品id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsId; // 执行语句

    /** // 保留原作者写的块注释
     * 商品类型 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsType; // 执行语句

    /** // 保留原作者写的块注释
     * 商品名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsName; // 执行语句

    /** // 保留原作者写的块注释
     * 商品交易价,单位分 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float goodsPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 商品详情json,可为空 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String goodsDetail; // 执行语句


} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-model/src/main/java/com/xuecheng/orders/model/po/XcPayRecord.java

package com.xuecheng.orders.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.FieldFill; // 导入 FieldFill 类
import com.baomidou.mybatisplus.annotation.TableField; // 导入 TableField 类
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("xc_pay_record") // 使用注解 @TableName("xc_pay_record")
public class XcPayRecord implements Serializable { // 定义 class XcPayRecord

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 支付记录号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 本系统支付交易号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long payNo; // 执行语句

    /** // 保留原作者写的块注释
     * 第三方支付交易流水号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outPayNo; // 执行语句

    /** // 保留原作者写的块注释
     * 第三方支付渠道编号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String outPayChannel; // 执行语句

    /** // 保留原作者写的块注释
     * 商品订单号 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long orderId; // 执行语句

    /** // 保留原作者写的块注释
     * 订单名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String orderName; // 执行语句
    /** // 保留原作者写的块注释
     * 订单总价单位元 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Float totalPrice; // 执行语句

    /** // 保留原作者写的块注释
     * 币种CNY // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String currency; // 执行语句

    /** // 保留原作者写的块注释
     * 创建时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 支付状态 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 支付成功时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime paySuccessTime; // 执行语句

    /** // 保留原作者写的块注释
     * 用户id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String userId; // 执行语句



} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-orders</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-orders-service</artifactId> <!-- SQL 语句片段 -->

    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-message-sdk</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-orders-model</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- MySQL 驱动 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>mysql</groupId> <!-- SQL 语句片段 -->
            <artifactId>mysql-connector-java</artifactId> <!-- SQL 语句片段 -->
            <scope>runtime</scope> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- mybatis plus的依赖 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.baomidou</groupId> <!-- SQL 语句片段 -->
            <artifactId>mybatis-plus-boot-starter</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 集成 Junit -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-test</artifactId> <!-- SQL 语句片段 -->
            <scope>test</scope> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
            <exclusions> <!-- SQL 语句片段 -->
                <exclusion> <!-- SQL 语句片段 -->
                    <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                    <artifactId>spring-boot-starter-logging</artifactId> <!-- SQL 语句片段 -->
                </exclusion> <!-- SQL 语句片段 -->
            </exclusions> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 log4j2 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-log4j2</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-amqp</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-freemarker</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Cloud 微服务远程调用 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-openfeign</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- 支付宝SDK -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alipay.sdk</groupId> <!-- SQL 语句片段 -->
            <artifactId>alipay-sdk-java</artifactId> <!-- SQL 语句片段 -->
            <version>3.7.73.ALL</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- 支付宝SDK依赖的日志 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>commons-logging</groupId> <!-- SQL 语句片段 -->
            <artifactId>commons-logging</artifactId> <!-- SQL 语句片段 -->
            <version>1.2</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuxueli</groupId> <!-- SQL 语句片段 -->
            <artifactId>xxl-job-core</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-amqp</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
    </dependencies> <!-- SQL 语句片段 -->

</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/config/AlipayConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径
 /** // 保留原作者写的块注释
 * @description 支付宝配置参数 // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/10/20 22:45 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 public class AlipayConfig { // 定义 class AlipayConfig
  // 商户appid // 保留原作者写的行内注释
//	public static String APPID = ""; // 保留原作者写的行内注释
  // 私钥 pkcs8格式的 // 保留原作者写的行内注释
//	public static String RSA_PRIVATE_KEY = ""; // 保留原作者写的行内注释
  // 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 // 保留原作者写的行内注释
  public static String notify_url = "http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/notify_url.jsp"; // 代码逻辑
  // 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址 // 保留原作者写的行内注释
  public static String return_url = "http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/return_url.jsp"; // 代码逻辑
  // 请求网关地址 // 保留原作者写的行内注释
  public static String URL = "https://openapi.alipaydev.com/gateway.do"; // 代码逻辑
  // 编码 // 保留原作者写的行内注释
  public static String CHARSET = "UTF-8"; // 把 "UTF-8" 赋值给 CHARSET
  // 返回格式 // 保留原作者写的行内注释
  public static String FORMAT = "json"; // 把 "json" 赋值给 FORMAT
  // 支付宝公钥 // 保留原作者写的行内注释
//	public static String ALIPAY_PUBLIC_KEY = ""; // 保留原作者写的行内注释
  // 日志记录目录 // 保留原作者写的行内注释
  public static String log_path = "/log"; // 把 "/log" 赋值给 log_path
  // RSA2 // 保留原作者写的行内注释
  public static String SIGNTYPE = "RSA2"; // 把 "RSA2" 赋值给 SIGNTYPE
 } // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/config/MybatisPlusConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.DbType; // 导入 DbType 类
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; // 导入 MybatisPlusInterceptor 类
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; // 导入 PaginationInnerInterceptor 类
import org.mybatis.spring.annotation.MapperScan; // 导入 MapperScan 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * <P> // 保留原作者写的块注释
 * 		Mybatis-Plus 配置 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
@MapperScan("com.xuecheng.orders.mapper") // 使用注解 @MapperScan("com.xuecheng.orders.mapper")
public class MybatisPlusConfig { // 定义 class MybatisPlusConfig
	/** // 保留原作者写的块注释
	 * 新的分页插件 // 保留原作者写的块注释
	 * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false // 保留原作者写的块注释
	 * 避免缓存出现问题(该属性会在旧插件移除后一同移除) // 保留原作者写的块注释
	 */ // 保留原作者写的块注释
	@Bean // 使用注解 @Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() { // 定义方法 mybatisPlusInterceptor(...)
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建 MybatisPlusInterceptor 对象并赋值给 interceptor
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 执行语句
		return interceptor; // 返回 interceptor
	} // 代码块结束


} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/config/PayNotifyConfig.java

package com.xuecheng.orders.config; // 声明类所在的包路径

import com.alibaba.fastjson.JSON; // 导入 JSON 类
import com.xuecheng.messagesdk.model.po.MqMessage; // 导入 MqMessage 类
import com.xuecheng.messagesdk.service.MqMessageService; // 导入 MqMessageService 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.amqp.core.*; // 导入 * 类
import org.springframework.amqp.rabbit.core.RabbitTemplate; // 导入 RabbitTemplate 类
import org.springframework.beans.BeansException; // 导入 BeansException 类
import org.springframework.beans.factory.annotation.Qualifier; // 导入 Qualifier 类
import org.springframework.context.ApplicationContext; // 导入 ApplicationContext 类
import org.springframework.context.ApplicationContextAware; // 导入 ApplicationContextAware 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/23 16:59 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Configuration // 使用注解 @Configuration
public class PayNotifyConfig implements ApplicationContextAware { // 定义 class PayNotifyConfig

    //交换机 // 保留原作者写的行内注释
    public static final String PAYNOTIFY_EXCHANGE_FANOUT = "paynotify_exchange_fanout"; // 把 "paynotify_exchange_fanout" 赋值给 PAYNOTIFY_EXCHANGE_FANOUT
    //支付结果通知消息类型 // 保留原作者写的行内注释
    public static final String MESSAGE_TYPE = "payresult_notify"; // 把 "payresult_notify" 赋值给 MESSAGE_TYPE
    //支付通知队列 // 保留原作者写的行内注释
    public static final String PAYNOTIFY_QUEUE = "paynotify_queue"; // 把 "paynotify_queue" 赋值给 PAYNOTIFY_QUEUE

    //声明交换机,且持久化 // 保留原作者写的行内注释
    @Bean(PAYNOTIFY_EXCHANGE_FANOUT) // 使用注解 @Bean(PAYNOTIFY_EXCHANGE_FANOUT)
    public FanoutExchange paynotify_exchange_fanout() { // 定义方法 paynotify_exchange_fanout(...)
        // 三个参数:交换机名称、是否持久化、当没有queue与其绑定时是否自动删除 // 保留原作者写的行内注释
        return new FanoutExchange(PAYNOTIFY_EXCHANGE_FANOUT, true, false); // 返回 new FanoutExchange(PAYNOTIFY_EXCHANGE_FANOUT, true, false)
    } // 代码块结束
    //支付通知队列,且持久化 // 保留原作者写的行内注释
    @Bean(PAYNOTIFY_QUEUE) // 使用注解 @Bean(PAYNOTIFY_QUEUE)
    public Queue course_publish_queue() { // 定义方法 course_publish_queue(...)
        return QueueBuilder.durable(PAYNOTIFY_QUEUE).build(); // 返回 QueueBuilder.durable(PAYNOTIFY_QUEUE).build()
    } // 代码块结束

    //交换机和支付通知队列绑定 // 保留原作者写的行内注释
    @Bean // 使用注解 @Bean
    public Binding binding_course_publish_queue(@Qualifier(PAYNOTIFY_QUEUE) Queue queue, @Qualifier(PAYNOTIFY_EXCHANGE_FANOUT) FanoutExchange exchange) { // 定义方法 binding_course_publish_queue(...)
        return BindingBuilder.bind(queue).to(exchange); // 返回 BindingBuilder.bind(queue).to(exchange)
    } // 代码块结束

    @Override // 使用注解 @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 定义方法 setApplicationContext(...)
        // 获取RabbitTemplate // 保留原作者写的行内注释
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class); // 把 applicationContext.getBean(RabbitTemplate.class) 赋值给 rabbitTemplate
        //消息处理service // 保留原作者写的行内注释
        MqMessageService mqMessageService = applicationContext.getBean(MqMessageService.class); // 把 applicationContext.getBean(MqMessageService.class) 赋值给 mqMessageService
        // 设置ReturnCallback // 保留原作者写的行内注释
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> { // 定义方法 方法(...)
            // 投递失败,记录日志 // 保留原作者写的行内注释
            log.info("消息发送失败,应答码{},原因{},交换机{},路由键{},消息{}", // 代码逻辑
                    replyCode, replyText, exchange, routingKey, message.toString()); // 执行语句
            MqMessage mqMessage = JSON.parseObject(message.toString(), MqMessage.class); // 把 JSON.parseObject(message.toString(), MqMessage.class) 赋值给 mqMessage
            //将消息再添加到消息表 // 保留原作者写的行内注释
            mqMessageService.addMessage(mqMessage.getMessageType(),mqMessage.getBusinessKey1(),mqMessage.getBusinessKey2(),mqMessage.getBusinessKey3()); // 执行语句

        }); // 执行语句
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper/XcOrdersGoodsMapper.java

package com.xuecheng.orders.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.orders.model.po.XcOrdersGoods; // 导入 XcOrdersGoods 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface XcOrdersGoodsMapper extends BaseMapper<XcOrdersGoods> { // 定义 interface XcOrdersGoodsMapper

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper/XcOrdersGoodsMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.orders.mapper.XcOrdersGoodsMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.orders.model.po.XcOrdersGoods"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="order_id" property="orderId" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_id" property="goodsId" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_type" property="goodsType" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_name" property="goodsName" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_price" property="goodsPrice" /> <!-- 字段与属性的映射规则 -->
        <result column="goods_detail" property="goodsDetail" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, order_id, goods_id, goods_type, goods_name, goods_price, goods_detail <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper/XcOrdersMapper.java

package com.xuecheng.orders.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.orders.model.po.XcOrders; // 导入 XcOrders 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface XcOrdersMapper extends BaseMapper<XcOrders> { // 定义 interface XcOrdersMapper

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper/XcOrdersMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.orders.mapper.XcOrdersMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.orders.model.po.XcOrders"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="total_price" property="totalPrice" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="user_id" property="userId" /> <!-- 字段与属性的映射规则 -->
        <result column="company_id" property="companyId" /> <!-- 字段与属性的映射规则 -->
        <result column="order_type" property="orderType" /> <!-- 字段与属性的映射规则 -->
        <result column="order_descrip" property="orderDescrip" /> <!-- 字段与属性的映射规则 -->
        <result column="order_detail" property="orderDetail" /> <!-- 字段与属性的映射规则 -->
        <result column="out_order_id" property="outOrderId" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, total_price, create_date, status, user_id, company_id, order_type, order_descrip, order_detail, out_order_id <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper/XcPayRecordMapper.java

package com.xuecheng.orders.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface XcPayRecordMapper extends BaseMapper<XcPayRecord> { // 定义 interface XcPayRecordMapper

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/mapper/XcPayRecordMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.orders.mapper.XcPayRecordMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.orders.model.po.XcPayRecord"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="pay_no" property="payNo" /> <!-- 字段与属性的映射规则 -->
        <result column="out_pay_no" property="outPayNo" /> <!-- 字段与属性的映射规则 -->
        <result column="out_pay_channel" property="outPayChannel" /> <!-- 字段与属性的映射规则 -->
        <result column="order_id" property="orderId" /> <!-- 字段与属性的映射规则 -->
        <result column="order_name" property="orderName" /> <!-- 字段与属性的映射规则 -->
        <result column="total_price" property="totalPrice" /> <!-- 字段与属性的映射规则 -->
        <result column="currency" property="currency" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="pay_success_time" property="paySuccessTime" /> <!-- 字段与属性的映射规则 -->
        <result column="user_id" property="userId" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, pay_no, out_pay_no, out_pay_channel, order_id,order_name, total_price, currency, create_date, status, pay_success_time, user_id <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/service/impl/OrderServiceImpl.java

package com.xuecheng.orders.service.impl; // 声明类所在的包路径

import com.alibaba.fastjson.JSON; // 导入 JSON 类
import com.alibaba.fastjson.JSONObject; // 导入 JSONObject 类
import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.request.AlipayTradeQueryRequest; // 导入 AlipayTradeQueryRequest 类
import com.alipay.api.response.AlipayTradeQueryResponse; // 导入 AlipayTradeQueryResponse 类
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 导入 LambdaQueryWrapper 类
import com.xuecheng.base.exception.XueChengPlusException; // 导入 XueChengPlusException 类
import com.xuecheng.base.utils.IdWorkerUtils; // 导入 IdWorkerUtils 类
import com.xuecheng.base.utils.QRCodeUtil; // 导入 QRCodeUtil 类
import com.xuecheng.messagesdk.model.po.MqMessage; // 导入 MqMessage 类
import com.xuecheng.messagesdk.service.MqMessageService; // 导入 MqMessageService 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import com.xuecheng.orders.config.PayNotifyConfig; // 导入 PayNotifyConfig 类
import com.xuecheng.orders.mapper.XcOrdersGoodsMapper; // 导入 XcOrdersGoodsMapper 类
import com.xuecheng.orders.mapper.XcOrdersMapper; // 导入 XcOrdersMapper 类
import com.xuecheng.orders.mapper.XcPayRecordMapper; // 导入 XcPayRecordMapper 类
import com.xuecheng.orders.model.dto.AddOrderDto; // 导入 AddOrderDto 类
import com.xuecheng.orders.model.dto.PayRecordDto; // 导入 PayRecordDto 类
import com.xuecheng.orders.model.dto.PayStatusDto; // 导入 PayStatusDto 类
import com.xuecheng.orders.model.po.XcOrders; // 导入 XcOrders 类
import com.xuecheng.orders.model.po.XcOrdersGoods; // 导入 XcOrdersGoods 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类
import com.xuecheng.orders.service.OrderService; // 导入 OrderService 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.amqp.core.Message; // 导入 Message 类
import org.springframework.amqp.core.MessageBuilder; // 导入 MessageBuilder 类
import org.springframework.amqp.core.MessageDeliveryMode; // 导入 MessageDeliveryMode 类
import org.springframework.amqp.rabbit.connection.CorrelationData; // 导入 CorrelationData 类
import org.springframework.amqp.rabbit.core.RabbitTemplate; // 导入 RabbitTemplate 类
import org.springframework.beans.BeanUtils; // 导入 BeanUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Service; // 导入 Service 类
import org.springframework.transaction.annotation.Transactional; // 导入 Transactional 类

import java.io.IOException; // 导入 IOException 类
import java.nio.charset.StandardCharsets; // 导入 StandardCharsets 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类
import java.util.List; // 导入 List 类
import java.util.Map; // 导入 Map 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 订单相关的接口 // 保留原作者写的块注释
 * @date 2023/2/26 10:12 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Service // 使用注解 @Service
public class OrderServiceImpl implements OrderService { // 定义 class OrderServiceImpl

    @Autowired // 使用注解 @Autowired
    XcOrdersMapper ordersMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    XcOrdersGoodsMapper ordersGoodsMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    MqMessageService mqMessageService; // 执行语句

    @Autowired // 使用注解 @Autowired
    XcPayRecordMapper payRecordMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    RabbitTemplate rabbitTemplate; // 执行语句

    @Autowired // 使用注解 @Autowired
    OrderServiceImpl currentProxy; // 执行语句

    @Value("${pay.qrcodeurl}") // 使用注解 @Value("${pay.qrcodeurl}")
    String qrcodeurl; // 执行语句

    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    @Transactional // 使用注解 @Transactional
    @Override // 使用注解 @Override
    public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto) { // 定义方法 createOrder(...)

        //插入订单表,订单主表,订单明细表 // 保留原作者写的行内注释
        XcOrders xcOrders = saveXcOrders(userId, addOrderDto); // 把 saveXcOrders(userId, addOrderDto) 赋值给 xcOrders

        //插入支付记录 // 保留原作者写的行内注释
        XcPayRecord payRecord = createPayRecord(xcOrders); // 把 createPayRecord(xcOrders) 赋值给 payRecord
        Long payNo = payRecord.getPayNo(); // 把 payRecord.getPayNo() 的返回值赋给 payNo

        //生成二维码 // 保留原作者写的行内注释
        QRCodeUtil qrCodeUtil = new QRCodeUtil(); // 创建 QRCodeUtil 对象并赋值给 qrCodeUtil
        //支付二维码的url // 保留原作者写的行内注释
        String url = String.format(qrcodeurl, payNo); // 把 String.format(qrcodeurl, payNo) 赋值给 url
        //二维码图片 // 保留原作者写的行内注释
        String qrCode = null; // 把变量 qrCode 初始化为 null
        try { // 尝试执行可能抛出异常的代码
            qrCode = qrCodeUtil.createQRCode(url, 200, 200); // 把 qrCodeUtil.createQRCode(url, 200, 200) 赋值给 qrCode
        } catch (IOException e) { // 定义方法 catch(...)
            XueChengPlusException.cast("生成二维码出错"); // 执行语句
        } // 代码块结束

        PayRecordDto payRecordDto = new PayRecordDto(); // 创建 PayRecordDto 对象并赋值给 payRecordDto
        BeanUtils.copyProperties(payRecord,payRecordDto); // 执行语句
        payRecordDto.setQrcode(qrCode); // 执行语句

        return payRecordDto; // 返回 payRecordDto
    } // 代码块结束

    @Override // 使用注解 @Override
    public XcPayRecord getPayRecordByPayno(String payNo) { // 定义方法 getPayRecordByPayno(...)
        XcPayRecord xcPayRecord = payRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo)); // 把 payRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo)) 赋值给 xcPayRecord
        return xcPayRecord; // 返回 xcPayRecord
    } // 代码块结束

    @Override // 使用注解 @Override
    public PayRecordDto queryPayResult(String payNo) { // 定义方法 queryPayResult(...)

        //调用支付宝的接口查询支付结果 // 保留原作者写的行内注释
        PayStatusDto payStatusDto = queryPayResultFromAlipay(payNo); // 把 queryPayResultFromAlipay(payNo) 赋值给 payStatusDto

        System.out.println(payStatusDto); // 执行语句
        //拿到支付结果更新支付记录表和订单表的支付状态 // 保留原作者写的行内注释
        currentProxy.saveAliPayStatus(payStatusDto); // 执行语句
        //要返回最新的支付记录信息 // 保留原作者写的行内注释
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNo); // 把 getPayRecordByPayno(payNo) 赋值给 payRecordByPayno
        PayRecordDto payRecordDto = new PayRecordDto(); // 创建 PayRecordDto 对象并赋值给 payRecordDto
        BeanUtils.copyProperties(payRecordByPayno,payRecordDto); // 执行语句

        return payRecordDto; // 返回 payRecordDto
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 请求支付宝查询支付结果 // 保留原作者写的块注释
     * @param payNo 支付交易号 // 保留原作者写的块注释
     * @return 支付结果 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public PayStatusDto queryPayResultFromAlipay(String payNo){ // 定义方法 queryPayResultFromAlipay(...)

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); // 创建 AlipayTradeQueryRequest 对象并赋值给 request
        JSONObject bizContent = new JSONObject(); // 创建 JSONObject 对象并赋值给 bizContent
        bizContent.put("out_trade_no", payNo); // 执行语句
        //bizContent.put("trade_no", "2014112611001004680073956707"); // 保留原作者写的行内注释
        request.setBizContent(bizContent.toString()); // 执行语句
        //支付宝返回的信息 // 保留原作者写的行内注释
        String body = null; // 把变量 body 初始化为 null
        try { // 尝试执行可能抛出异常的代码
            AlipayTradeQueryResponse response = alipayClient.execute ( request ); //通过alipayClient调用API,获得对应的response类 // 把 alipayClient.execute ( request ) 赋值给 response
            if(!response.isSuccess()){//交易不成功 // 定义方法 方法(...)
                XueChengPlusException.cast("请求支付宝查询支付结果失败"); // 执行语句
            } // 代码块结束
            body = response.getBody(); // 把 response.getBody() 的返回值赋给 body
        } catch (AlipayApiException e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
           XueChengPlusException.cast("请求支付查询支付结果异常"); // 执行语句
        } // 代码块结束
        Map bodyMap = JSON.parseObject(body, Map.class); // 把 JSON.parseObject(body, Map.class) 赋值给 bodyMap
        Map alipay_trade_query_response = (Map) bodyMap.get("alipay_trade_query_response"); // 把 (Map) bodyMap.get("alipay_trade_query_response") 赋值给 alipay_trade_query_response

        //解析支付结果 // 保留原作者写的行内注释
        String trade_no = (String) alipay_trade_query_response.get("trade_no"); // 把 (String) alipay_trade_query_response.get("trade_no") 赋值给 trade_no
        String trade_status = (String) alipay_trade_query_response.get("trade_status"); // 把 (String) alipay_trade_query_response.get("trade_status") 赋值给 trade_status
        String total_amount = (String) alipay_trade_query_response.get("total_amount"); // 把 (String) alipay_trade_query_response.get("total_amount") 赋值给 total_amount
        PayStatusDto payStatusDto = new PayStatusDto(); // 创建 PayStatusDto 对象并赋值给 payStatusDto
        payStatusDto.setOut_trade_no(payNo); // 执行语句
        payStatusDto.setTrade_no(trade_no);//支付宝的交易号 // 执行语句
        payStatusDto.setTrade_status(trade_status);//交易状态 // 执行语句
        payStatusDto.setApp_id(APP_ID); // 执行语句
        payStatusDto.setTotal_amount(total_amount);//总金额 // 执行语句


        return payStatusDto; // 返回 payStatusDto
    } // 代码块结束

    /** // 保留原作者写的块注释
     * @description 保存支付宝支付结果 // 保留原作者写的块注释
     * @param payStatusDto  支付结果信息 从支付宝查询到的信息 // 保留原作者写的块注释
     * @return void // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/10/4 16:52 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @Transactional // 使用注解 @Transactional
    public void saveAliPayStatus(PayStatusDto payStatusDto){ // 定义方法 saveAliPayStatus(...)
        //支付记录号 // 保留原作者写的行内注释
        String payNO = payStatusDto.getOut_trade_no(); // 把 payStatusDto.getOut_trade_no() 的返回值赋给 payNO
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNO); // 把 getPayRecordByPayno(payNO) 赋值给 payRecordByPayno
        if(payRecordByPayno == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("找不到相关的支付记录"); // 执行语句
        } // 代码块结束
        //拿到相关联的订单id // 保留原作者写的行内注释
        Long orderId = payRecordByPayno.getOrderId(); // 把 payRecordByPayno.getOrderId() 的返回值赋给 orderId
        XcOrders xcOrders = ordersMapper.selectById(orderId); // 把 ordersMapper.selectById(orderId) 赋值给 xcOrders
        if(xcOrders == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("找不到相关联的订单"); // 执行语句
        } // 代码块结束
        //支付状态 // 保留原作者写的行内注释
        String statusFromDb = payRecordByPayno.getStatus(); // 把 payRecordByPayno.getStatus() 的返回值赋给 statusFromDb
        //如果数据库支付的状态已经是成功了,不再处理了 // 保留原作者写的行内注释
        if("601002".equals(statusFromDb)){ // 定义方法 方法(...)
            return ; // 返回 
        } // 代码块结束

        //如果支付成功 // 保留原作者写的行内注释
        String trade_status = payStatusDto.getTrade_status();//从支付宝查询到的支付结果 // 把 payStatusDto.getTrade_status() 的返回值赋给 trade_status
        if(trade_status.equals("TRADE_SUCCESS")){//支付宝返回的信息为支付成功 // 定义方法 方法(...)
            //更新支付记录表的状态为支付成功 // 保留原作者写的行内注释
            payRecordByPayno.setStatus("601002"); // 执行语句
            //支付宝的订单号 // 保留原作者写的行内注释
            payRecordByPayno.setOutPayNo(payStatusDto.getTrade_no()); // 执行语句
            //第三方支付渠道编号 // 保留原作者写的行内注释
            payRecordByPayno.setOutPayChannel("Alipay"); // 执行语句
            //支付成功时间 // 保留原作者写的行内注释
            payRecordByPayno.setPaySuccessTime(LocalDateTime.now()); // 执行语句
            payRecordMapper.updateById(payRecordByPayno); // 执行语句

            //更新订单表的状态为支付成功 // 保留原作者写的行内注释
            xcOrders.setStatus("600002");//订单状态为交易成功 // 执行语句
            ordersMapper.updateById(xcOrders); // 执行语句

            //将消息写到数据库 // 保留原作者写的行内注释
            MqMessage mqMessage = mqMessageService.addMessage("payresult_notify", xcOrders.getOutBusinessId(), xcOrders.getOrderType(), null); // 把 mqMessageService.addMessage("payresult_notify", xcOrders.getOutBusinessId(), xcOrders.getOrderType(), null) 赋值给 mqMessage
            //发送消息 // 保留原作者写的行内注释
            notifyPayResult(mqMessage); // 执行语句

        } // 代码块结束




    } // 代码块结束



    @Override // 使用注解 @Override
    public void notifyPayResult(MqMessage message) { // 定义方法 notifyPayResult(...)

        //消息内容 // 保留原作者写的行内注释
        String jsonString = JSON.toJSONString(message); // 把 JSON.toJSONString(message) 赋值给 jsonString
        //创建一个持久化消息 // 保留原作者写的行内注释
        Message messageObj = MessageBuilder.withBody(jsonString.getBytes(StandardCharsets.UTF_8)).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build(); // 把 MessageBuilder.withBody(jsonString.getBytes(StandardCharsets.UTF_8)).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build() 的返回值赋给 messageObj

        //消息id // 保留原作者写的行内注释
        Long id = message.getId(); // 把 message.getId() 的返回值赋给 id

        //全局消息id // 保留原作者写的行内注释
        CorrelationData correlationData = new CorrelationData(id.toString()); // 创建 CorrelationData 对象并赋值给 correlationData

        //使用correlationData指定回调方法 // 保留原作者写的行内注释
        correlationData.getFuture().addCallback(result->{ // 定义方法 方法(...)
            if(result.isAck()){ // 定义方法 方法(...)
                //消息成功发送到了交换机 // 保留原作者写的行内注释
                log.debug("发送消息成功:{}",jsonString); // 执行语句
                //将消息从数据库表mq_message删除 // 保留原作者写的行内注释
                mqMessageService.completed(id); // 执行语句

            }else{ // 代码逻辑
                //消息发送失败 // 保留原作者写的行内注释
                log.debug("发送消息失败:{}",jsonString); // 执行语句
            } // 代码块结束

        },ex->{ // 代码逻辑
            //发生异常了 // 保留原作者写的行内注释
            log.debug("发送消息异常:{}",jsonString); // 执行语句
        }); // 执行语句
        //发送消息 // 保留原作者写的行内注释
        rabbitTemplate.convertAndSend(PayNotifyConfig.PAYNOTIFY_EXCHANGE_FANOUT,"",messageObj,correlationData); // 执行语句
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 保存支付记录 // 保留原作者写的块注释
     * @param orders // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public XcPayRecord createPayRecord(XcOrders orders){ // 定义方法 createPayRecord(...)
        //订单id // 保留原作者写的行内注释
        Long orderId = orders.getId(); // 把 orders.getId() 的返回值赋给 orderId
        XcOrders xcOrders = ordersMapper.selectById(orderId); // 把 ordersMapper.selectById(orderId) 赋值给 xcOrders
        //如果此订单不存在不能添加支付记录 // 保留原作者写的行内注释
        if(xcOrders == null){ // 定义方法 方法(...)
            XueChengPlusException.cast("订单不存在"); // 执行语句
        } // 代码块结束
        //订单状态 // 保留原作者写的行内注释
        String status = xcOrders.getStatus(); // 把 xcOrders.getStatus() 的返回值赋给 status
        //如果此订单支付结果为成功,不再添加支付记录,避免重复支付 // 保留原作者写的行内注释
        if("601002".equals(status)){//支付成功 // 定义方法 方法(...)
            XueChengPlusException.cast("此订单已支付"); // 执行语句
        } // 代码块结束
        //添加支付记录 // 保留原作者写的行内注释
        XcPayRecord xcPayRecord = new XcPayRecord(); // 创建 XcPayRecord 对象并赋值给 xcPayRecord
        xcPayRecord.setPayNo(IdWorkerUtils.getInstance().nextId());//支付记录号,将来要传给支付宝 // 执行语句
        xcPayRecord.setOrderId(orderId); // 执行语句
        xcPayRecord.setOrderName(xcOrders.getOrderName()); // 执行语句
        xcPayRecord.setTotalPrice(xcOrders.getTotalPrice()); // 执行语句
        xcPayRecord.setCurrency("CNY"); // 执行语句
        xcPayRecord.setCreateDate(LocalDateTime.now()); // 执行语句
        xcPayRecord.setStatus("601001");//未支付 // 执行语句
        xcPayRecord.setUserId(xcOrders.getUserId()); // 执行语句
        int insert = payRecordMapper.insert(xcPayRecord); // 把 payRecordMapper.insert(xcPayRecord) 赋值给 insert
        if(insert<=0){ // 定义方法 方法(...)
            XueChengPlusException.cast("插入支付记录失败"); // 执行语句
        } // 代码块结束
        return xcPayRecord; // 返回 xcPayRecord
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 保存订单信息 // 保留原作者写的块注释
     * @param userId // 保留原作者写的块注释
     * @param addOrderDto // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public XcOrders saveXcOrders(String userId, AddOrderDto addOrderDto){ // 定义方法 saveXcOrders(...)
        //插入订单表,订单主表,订单明细表 // 保留原作者写的行内注释
        //进行幂等性判断,同一个选课记录只能有一个订单 // 保留原作者写的行内注释
        XcOrders xcOrders = getOrderByBusinessId(addOrderDto.getOutBusinessId()); // 把 getOrderByBusinessId(addOrderDto.getOutBusinessId()) 赋值给 xcOrders
        if(xcOrders!=null){ // 定义方法 方法(...)
            return xcOrders; // 返回 xcOrders
        } // 代码块结束

        //插入订单主表 // 保留原作者写的行内注释
        xcOrders = new XcOrders(); // 创建 XcOrders 对象并赋值给 xcOrders
        //使用雪花算法生成订单号 // 保留原作者写的行内注释
        xcOrders.setId(IdWorkerUtils.getInstance().nextId()); // 执行语句
        xcOrders.setTotalPrice(addOrderDto.getTotalPrice()); // 执行语句
        xcOrders.setCreateDate(LocalDateTime.now()); // 执行语句
        xcOrders.setStatus("600001");//未支付 // 执行语句
        xcOrders.setUserId(userId); // 执行语句
        xcOrders.setOrderType("60201");//订单类型 // 执行语句
        xcOrders.setOrderName(addOrderDto.getOrderName()); // 执行语句
        xcOrders.setOrderDescrip(addOrderDto.getOrderDescrip()); // 执行语句
        xcOrders.setOrderDetail(addOrderDto.getOrderDetail()); // 执行语句
        xcOrders.setOutBusinessId(addOrderDto.getOutBusinessId());//如果是选课这里记录选课表的id // 执行语句
        int insert = ordersMapper.insert(xcOrders); // 把 ordersMapper.insert(xcOrders) 赋值给 insert
        if(insert<=0){ // 定义方法 方法(...)
            XueChengPlusException.cast("添加订单失败"); // 执行语句
        } // 代码块结束
        //订单id // 保留原作者写的行内注释
        Long orderId = xcOrders.getId(); // 把 xcOrders.getId() 的返回值赋给 orderId
        //插入订单明细表 // 保留原作者写的行内注释
        //将前端传入的明细json串转成List // 保留原作者写的行内注释
        String orderDetailJson = addOrderDto.getOrderDetail(); // 把 addOrderDto.getOrderDetail() 的返回值赋给 orderDetailJson
        List<XcOrdersGoods> xcOrdersGoods = JSON.parseArray(orderDetailJson, XcOrdersGoods.class); // 把 JSON.parseArray(orderDetailJson, XcOrdersGoods.class) 赋值给 xcOrdersGoods
        //遍历xcOrdersGoods插入订单明细表 // 保留原作者写的行内注释
        xcOrdersGoods.forEach(goods->{ // 定义方法 方法(...)

            goods.setOrderId(orderId); // 执行语句
            //插入订单明细表 // 保留原作者写的行内注释
            int insert1 = ordersGoodsMapper.insert(goods); // 把 ordersGoodsMapper.insert(goods) 赋值给 insert1

        }); // 执行语句
        return xcOrders; // 返回 xcOrders

    } // 代码块结束


    /** // 保留原作者写的块注释
     * 根据业务id查询订单 ,业务id是选课记录表中的主键 // 保留原作者写的块注释
     * @param businessId // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public XcOrders getOrderByBusinessId(String businessId) { // 定义方法 getOrderByBusinessId(...)
        XcOrders orders = ordersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId)); // 把 ordersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId)) 赋值给 orders
        return orders; // 返回 orders
    } // 代码块结束



} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/main/java/com/xuecheng/orders/service/OrderService.java

package com.xuecheng.orders.service; // 声明类所在的包路径

import com.xuecheng.messagesdk.model.po.MqMessage; // 导入 MqMessage 类
import com.xuecheng.orders.model.dto.AddOrderDto; // 导入 AddOrderDto 类
import com.xuecheng.orders.model.dto.PayRecordDto; // 导入 PayRecordDto 类
import com.xuecheng.orders.model.dto.PayStatusDto; // 导入 PayStatusDto 类
import com.xuecheng.orders.model.po.XcPayRecord; // 导入 XcPayRecord 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 订单相关的service接口 // 保留原作者写的块注释
 * @date 2023/2/26 10:11 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface OrderService { // 定义 interface OrderService

 /** // 保留原作者写的块注释
  * @description 创建商品订单 // 保留原作者写的块注释
  * @param addOrderDto 订单信息 // 保留原作者写的块注释
  * @return PayRecordDto 支付记录(包括二维码) // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/10/4 11:02 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto); // 执行语句

 /** // 保留原作者写的块注释
  * @description 查询支付记录 // 保留原作者写的块注释
  * @param payNo  交易记录号 // 保留原作者写的块注释
  * @return com.xuecheng.orders.model.po.XcPayRecord // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/10/20 23:38 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public XcPayRecord getPayRecordByPayno(String payNo); // 执行语句

 /** // 保留原作者写的块注释
  * 请求支付宝查询支付结果 // 保留原作者写的块注释
  * @param payNo 支付记录id // 保留原作者写的块注释
  * @return 支付记录信息 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public PayRecordDto queryPayResult(String payNo); // 执行语句

 /** // 保留原作者写的块注释
  * 保存支付状态 // 保留原作者写的块注释
  * @param payStatusDto // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public void saveAliPayStatus(PayStatusDto payStatusDto); // 执行语句

 /** // 保留原作者写的块注释
  * 发送通知结果 // 保留原作者写的块注释
  * @param message // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public void notifyPayResult(MqMessage message); // 执行语句
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/test/java/com/xuecheng/orders/AliPayTest.java

package com.xuecheng.orders; // 声明类所在的包路径

import com.alibaba.fastjson.JSONObject; // 导入 JSONObject 类
import com.alipay.api.AlipayApiException; // 导入 AlipayApiException 类
import com.alipay.api.AlipayClient; // 导入 AlipayClient 类
import com.alipay.api.DefaultAlipayClient; // 导入 DefaultAlipayClient 类
import com.alipay.api.request.AlipayTradeQueryRequest; // 导入 AlipayTradeQueryRequest 类
import com.alipay.api.response.AlipayTradeQueryResponse; // 导入 AlipayTradeQueryResponse 类
import com.xuecheng.orders.config.AlipayConfig; // 导入 AlipayConfig 类
import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.boot.test.context.SpringBootTest; // 导入 SpringBootTest 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 请求支付宝查询订单状态 // 保留原作者写的块注释
 * @date 2023/2/25 16:49 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@SpringBootTest // 使用注解 @SpringBootTest
public class AliPayTest { // 定义 class AliPayTest

    @Value("${pay.alipay.APP_ID}") // 使用注解 @Value("${pay.alipay.APP_ID}")
    String APP_ID; // 执行语句
    @Value("${pay.alipay.APP_PRIVATE_KEY}") // 使用注解 @Value("${pay.alipay.APP_PRIVATE_KEY}")
    String APP_PRIVATE_KEY; // 执行语句

    @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}") // 使用注解 @Value("${pay.alipay.ALIPAY_PUBLIC_KEY}")
    String ALIPAY_PUBLIC_KEY; // 执行语句

    @Test // 使用注解 @Test
    public void queryPayResult() throws AlipayApiException { // 定义方法 queryPayResult(...)

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE); // 创建 DefaultAlipayClient 对象并赋值给 alipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); // 创建 AlipayTradeQueryRequest 对象并赋值给 request
        JSONObject bizContent = new JSONObject(); // 创建 JSONObject 对象并赋值给 bizContent
        bizContent.put("out_trade_no", "1629685380690747392"); // 执行语句
        //bizContent.put("trade_no", "2014112611001004680073956707"); // 保留原作者写的行内注释
        request.setBizContent(bizContent.toString()); // 执行语句
        AlipayTradeQueryResponse response = alipayClient.execute ( request ); //通过alipayClient调用API,获得对应的response类 // 把 alipayClient.execute ( request ) 赋值给 response
        String body = response.getBody(); // 把 response.getBody() 的返回值赋给 body
        System.out.print( body); // 执行语句

} // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/test/java/com/xuecheng/orders/OrdersApplication.java

package com.xuecheng.orders; // 声明类所在的包路径


import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类
import org.springframework.cloud.openfeign.EnableFeignClients; // 导入 EnableFeignClients 类

@SpringBootApplication // 使用注解 @SpringBootApplication
public class OrdersApplication { // 定义 class OrdersApplication
	public static void main(String[] args) { // 定义方法 main(...)
		SpringApplication.run(OrdersApplication.class, args); // 执行语句
	} // 代码块结束
} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/test/java/com/xuecheng/orders/Test1.java

package com.xuecheng.orders; // 声明类所在的包路径

import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.boot.test.context.SpringBootTest; // 导入 SpringBootTest 类

/** // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/10/2 10:32 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 @SpringBootTest // 使用注解 @SpringBootTest
public class Test1 { // 定义 class Test1


  @Test // 使用注解 @Test
 public void test(){ // 定义方法 test(...)

  } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/test/resources/bootstrap.yml

spring:
  application:
    name: orders-service
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true

  #profiles默认为dev
  profiles:
    active: dev




文件:xuecheng-plus-orders/xuecheng-plus-orders-service/src/test/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<Configuration monitorInterval="180" packages=""> <!-- SQL 语句片段 -->
    <properties> <!-- SQL 语句片段 -->
        <property name="logdir">logs</property> <!-- SQL 语句片段 -->
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property> <!-- SQL 语句片段 -->
    </properties> <!-- SQL 语句片段 -->
    <Appenders> <!-- SQL 语句片段 -->
        <Console name="Console" target="SYSTEM_OUT"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
        </Console> <!-- SQL 语句片段 -->

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="ErrorAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Async> <!-- SQL 语句片段 -->
    </Appenders> <!-- SQL 语句片段 -->
    
    <Loggers> <!-- SQL 语句片段 -->
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="org.mybatis" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="springfox" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		<logger name="org.apache.http" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="com.netflix.discovery" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        
        <logger name="RocketmqCommon"  level="INFO" > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqRemoting" level="INFO"  > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqClient" level="WARN"> <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.lottery" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.bonuspoint" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="AsyncAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="Console"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Root> <!-- SQL 语句片段 -->
    </Loggers> <!-- SQL 语句片段 -->
</Configuration> <!-- SQL 语句片段 -->
appendix_G
https://clxhxhhr.top/posts/4374/
作者
clxstart
发布于
2026-09-26
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。